关于this的全棉解析(上)的文章地址segmentfault
函数是否在new中调用(new绑定)?若是是的话this绑定的是新建立的对象。浏览器
bar = new foo()安全
函数是否经过call、apply(显式绑定)或者硬绑定调用?若是是的话,this绑定的是指定的对象。app
bar = foo.call(obj2)函数
函数是否在某个上下文对象中调用(隐式绑定)?若是是的话,this绑定的是那个上下文对象。this
bar = obj1.foo()prototype
若是都不是的话,使用默认绑定。若是在严格模式下,就绑定到undefined,不然绑定到全局对象。code
bar = foo();对象
若是把null或者undefined做为this的绑定对象传入call、apply或者bind,这些值在调用时会被忽略,实际应用的是默认绑定规则。ip
function foo() { console.log(this.a); } var a = 2; foo.call(null); //2
然而,老是使用null来忽略this绑定可能产生一些反作用。若是某个函数确实使用了this,那默认绑定规则会把this绑定到全局对象(在浏览器中全局对象为window),这将致使不可预计的后果(好比修改全局对象)。
显而易见,这种方式可能会致使许多难以分析和追踪的bug。
一种“更安全”的作法是传入一个特殊的对象、把this绑定到这个对象不会对你的程序产生反作用。
在JavaScript中建立一个空对象最简单的方法都是Object.create(null),可是并不会建立Object.prototype这个委托。
function foo(a, b) { console.log("a:" + a + ", b:" + b); } //建立一个新对象 var emptyObj = Object.create(null); foo.apply(emptyObj, [2, 3]) var bar = foo.bind(emptyObj, 2); bar(3);
间接引用最容易在赋值时发生。
function foo() { console.log(this.a); } var a = 2; var o = { a: 3, foo: foo }; var p = { a: 4 }; o.foo(); //3 (p.foo = o.foo)() //2
赋值表达式p.foo= o.foo的返回值是目标函数的引用,所以调用位置是foo()而不是p.foo()或者o.foo(),因此绑定的是全局对象。
若是要判断一个运行中函数的this绑定,就须要找到这个函数的直接调用位置。找到以后就能够顺序应用下面这四条规则来判断this的绑定对象。
由new调用?绑定到新建立的对象。
由call或者apply(或者bind)调用?绑定到指定的对象。
由上下文对象调用?绑定到那个上下文对象。
默认:在严格模式下绑定到undefined,不然绑定到全局对象。