这是我参与8月更文挑战的第二十一天,活动详情查看:8月更文挑战
间接引用
另一个需要注意的是,在编码过程中很有可能传呼机一个函数的“间接引用”,在这种情况下,调用这个函数会应用默认绑定规则。间接引用最容易在赋值时发生:
function foo(){
console.log(this.a);
}
var a = 2;
var o = {
a : 2,
foo: foo
};
var p = {
a : 4
};
o.foo(); //3
(p.foo = o.foo)(); //2
赋值表达式p.foo = o.foo的返回值是目标函数的引用,因此调用位置是foo()而不是p.foo()或者o.foo()。
软绑定
之前我们体验了硬绑定可以把this强制绑定到指定的对象(除了使用new时)防止函数调用引用默认绑定规则。但是硬绑定大大降低了函数的灵活性,是用硬绑定之后就无法使用隐式或者显式绑定来修改this。于是我们有一种软绑定的方法实现:
if(!Function.prototype.softBind){
Function.prototype.softBind = function(obj){
var fn = this;
var curried = [].slice.call(arguments,1);
var bound = function(){
return fn.apply(
(!this||this === (window || global))?obj:this,
curried.concat.apply(curried,arguments)
);
};
bound.prototype = Object.create(fn.prototype);
return bound;
};
}
它会对指定的函数进行封装,首先检查调用时的this,如果this绑定到全局对象或者undefined,那就把指定的默认对象obj绑定到this,否则不会修改this。
this词法
我们之前讲的四条规则可以包含所有的正常函数。但是ES6中的箭头函数并不适用这四条规则。箭头函数的this完全根据外层(函数或者全局)作用域来决定。 箭头函数最常用于回调函数中,例如事件处理器或者定时器:
function foo(){
setTimeout(() => {
console.log(this.a);
},1000);
}
var obj = {
a :2
};
foo.call(obj); //2
箭头函数可以想bind一样确保函数的this被绑定到指定对象,此外,它的重要性还体现在它用更常见的词法作用域取代了传统的this机制。箭头函数会继承外层函数调用的this绑定(无论this绑定到什么)。