1. 被忽略的this
如果你传递null或者undefined作为call,apply,或bind的this绑定参数,那么这些值会被忽略掉,取而代之的是默认绑定规则将适用于这个调用。在严格模式下(被调函数内部使用strict模式), this等于undefined, 在非严格模式下,this指向global对象(在浏览器中是window)。
2. 防止this绑定退回到默认绑定的措施
2.1 空对象 {}
2.2 DMZ对象 Object.create(null)
如果想让使用的函数不关心this,可以传递一个空对象作为thisArgs, 但空对象的原型指向Object.prototype,在Object.prototype上添加的任何属性都会影响到大多数对象,因为绝大多数对象原型链终端都是Object.prototype,为了隔离这个副作用,可以传递一个完全为空的对象Object.create(null), 任何对this的隐藏或意外的使用将会被限制在这个空对象中。
2.3 软化绑定
防止退回到默认绑定,意外的修改global对象,同时保持函数可以通过隐含绑定或显式绑定来手动绑定this。
if(!Function.prototype.softBind) {
Function.prototype.softBind = function (obj) {
var fn = this;
curried = [].slice.call(arguments,1),
bound = function bound() {
return fn.apply( (!this || (typeof window !== "undefined" && this === window)
|| ( typeof global !== "undefined" && this === global)
) ? obj : this,
curried.concat.apply(curried,arguments)
);
};
bound.prototype = Object.create(fn.prototype);
return bound;
};
}
function foo() {
console.log("name:" + this.name);
}
var obj = {name:"obj"},
obj2 = {name:"obj2"},
obj3 = {name:"obj3"};
var fooOBJ = foo.softBind(obj);
fooOBJ();//name: obj
obj2.foo = foo.softBind(obj);
obj2.foo();//name: obj2
fooOBJ.call(obj3);
setTimeout(obj2.foo,10);//name: obj 退回到软绑定