硬绑定这种方式可以把this强制绑定到指定的对象,防止函数调用应用默认绑定规则。硬绑定会大大降低函数的灵活性,使用硬绑定之后无法使用应隐式绑定或显式绑定来修改this。
//软绑定代码
if( !Function.prototype.softBind) {
Function.prototype.softBind = function(obj){
var fn = this;
//捕获所有curried 参数
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.creat( fn.prototype );
return bound;
}
}
softBind(...)的原理和ES5内置的bind(..)类似。它会对指定的函数进行封装,首先检查调用时的this,如果this绑定到全局对象或者undefined,那就把指定的默认对象obj绑定到this,否则不会修改this.此外,这段代码还支持可选的柯里化。
function foo(){
//返回一个箭头函数
return (a)=>{
//this 继承自 foo()
console.log( this.a );
}
}
var obj1 ={
a : 2
};
var obj2 = {
a : 3
};
var bar = foo.call( obj1 );
bar.call( obj2 ); //2
foo() 内部创建的箭头函数会捕获调用时foo()的 this。由于foo()的this绑定到obj1,bar(引用箭头函数)的this, bar (引用箭头函数)的this也会绑定到obj1,箭头函数的绑定无法被修改。
function foo() {
setTimeout( ()=>{
//这里的this在词法上继承自foo()
console.log( this.a );
},1000);
}
var obj = {
a:2
}
foo.call( obj ); //2
箭头函数可以像bind()一样确保函数的this被绑定到指定对象,此外,其重要性还体现在它用更常见的词法作用域取代了传统的this机制。实际上,在ES6之前我们就已经在使用一种几乎和箭头函数完全一样的模式。
function foo(){
var self = this;
setTimeout( fucntion(){
console.log(self.a)
},1000)
}
var obj = {
a : 2
};
foo.call( obj ); //2