bind、apply、call - freddielovekqy/dung-beetle GitHub Wiki
apply与call的底层实现原理,都是讲方法本身赋值给传递的新的this对象,作为新的this对象的一个属性,执行this对象的这个方法,来重定向方法内的this值。 apply与call除了方法参数的设置方式外,在原理上也没有任何区别。
Function.prototype.newCall = function (content, ...args) {
content = content || window;
content.fn = this;
const result = content.fn(...args);
delete content.fn;
return result;
}
Function.prototype.newApply = function (content, args) {
content = content || window;
content.fn = this;
const result = content.fn(...args);
delete content.fn;
return result;
}
bind底层原理实现与上面两种方式不同,但是底层也是通过call或者apply与闭包来实现的。bind返回一个新的方法对象。
Function.prototype.myBind = function (context, ...bindArgs) {
if (typeof this !== 'function') {
throw new TypeError('this is not a function');
}
const _this = this;
return function Fn(...execArgs) {
const args = bindArgs.concat(execArgs);
return _this.call(this instanceof Fn ? this : context, ...args);
}
}
注意:bind
无法连续两次使用修改一个方法内的this
指向,多次使用,this指向总是指向第一次调用时传入的值。
原因是:bind
返回的新的方法中,包含闭包,第二次使用bind
的时候,return后的_this
实际上是前一个bind
新返回的Fn
方法,Fn
方法在执行时,方法内的_this
指向老的方法,this
值为window
,所以.call
执行时传入的内容是第一次调用bind
时候产生的context
值,即第一次调用bind
时候传入的this指向。