三者的区别
- 三者多可以显式绑定函数的this指向
- 三者第一个参数都是this指向的对象,若该参数为undefined或null,this则默认指向全局window
- 传参不同,apply是数组,call是参数列表,而bind可以分为多次传入,实现参数合并
- call、apply是立即执行,bind是返回绑定this之后的函数,如果这个新的函数作为构造函数被调用,那么this不再指向传入给bind的第一个参数,而是指向新生成的对象
myCall
在调用 func 时要使用的 this 值。如果函数不在严格模式下,null 和 undefined 将被替换为全局对象,并且原始值将被转换为对象。
如果省略第一个 thisArg 参数,则默认为 undefined。在非严格模式下,this 值将被替换为 globalThis(类似于全局对象)。
Function.prototype.myCall = function (thisArg, ...args) {thisArg = thisArg || windowlet fn = Symbol()// this指向调用的call函数thisArg[fn] = this// 隐式绑定this,如执行obj.foo(),this指向objlet result = thisArg[fn](...args)// 执行完后删除增加的属性delete thisArg[fn]return result
}
myApply
thisArg
调用 func 时提供的 this 值。如果函数不处于严格模式,则 null 和 undefined 会被替换为全局对象,原始值会被转换为对象。
argsArray 可选
一个类数组对象,用于指定调用 func 时的参数,或者如果不需要向函数提供参数,则为 null 或 undefined。
Function.prototype.myApply = function (thisArg, args) {thisArg = thisArg || windowlet fn = Symbol()// this指向调用的call函数thisArg[fn] = this// 隐式绑定this,如执行obj.foo(),this指向objlet result = thisArg[fn](...args)// 执行完后删除增加的属性delete thisArg[fn]return result
}
myBind
bind 是返回绑定this之后的函数,如果这个新的函数作为构造函数被调用,那么this不再指向传入给bind的第一个参数,而是指向新的实例
thisArg
在调用绑定函数时,作为 this 参数传入目标函数 func 的值。如果函数不在严格模式下,null 和 undefined 会被替换为全局对象,并且原始值会被转换为对象。如果使用 new 运算符构造绑定函数,则忽略该值。
arg1, …, argN 可选
在调用 func 时,插入到传入绑定函数的参数前的参数。
// bind 是返回绑定this之后的函数,如果这个新的函数作为构造函数被调用,那么this不再指向传入给bind的第一个参数,而是指向新的实例
Function.prototype.myBind = function (thisArg, ...args) {thisArg = thisArg || windowlet fn = thislet f = Symbol()const result = function (...args1) {if (this instanceof fn) {// 如果作为构造函数调用,this指向实例this[f] = fnlet res = this[f](...args, ...args1)delete this[f]return res} else {// bind返回函数作为普通函数调用时let res = thisArg[f](...args, ...args1)return res}}// 如果绑定的是构造函数,那么需要继承构造函数原型属性和方法result.prototype = Object.create(fn.prototype)return result
}