在上一章,我们已经知道了一共有4种绑定的方式
1.默认绑定
2.隐式绑定
3.显示绑定
4.new绑定
如果你不记得的话请看上一节 传送点
在这4种绑定中,我们知道默认绑定的级别是最低的!!!!!为什么?
因为上面的所有都不能用了才考虑默认绑定,请考虑下面的代码
var obj={
d:10,
fn:function(){
console.log(this.d);//10
function foo(){
console.log(this);//window
console.log(this.d);//undefined
}
foo();//在这里只是一个函数调用!!!!!!!!!!!!,所以指向的是window
}
}
obj.fn();
所以说默认绑定的级别是最低的
隐式绑定vs显示绑定
function foo(){
console.log(this.a);
}
var b={
a:100,
foo:foo
};
var b2={
a:200,
foo:foo
};
b.foo();//100
b2.foo();//200
b.foo.call(b2);//200
b2.foo.call(b);//100
可以看到显示绑定的优先级别高于隐式绑定
隐式绑定 vs new绑定
function foo(something) {
this.a = something;
}
var obj1 = {
foo: foo
};
var obj2 = {};
obj1.foo( 2 );
console.log( obj1.a ); // 2
obj1.foo.call( obj2, 3 );
console.log( obj2.a ); // 3
var bar = new obj1.foo( 4 );
console.log( obj1.a ); // 2
console.log( bar.a ); // 4
可以看到New绑定高于隐式绑定
显示绑定 vs New绑定
function foo(something) {
this.a = something;
}
var obj1 = {};
var bar = foo.bind( obj1 );
bar( 2 );
console.log( obj1.a ); // 2
var baz = new bar(3);
console.log( obj1.a ); // 2
console.log( baz.a ); // 3
判断 this
现在我们可以根据优先级来判断函数在某个调用位置应用的是哪条规则。可以按照下面的
顺序来进行判断:
1. 函数是否在 new 中调用( new 绑定)?如果是的话 this 绑定的是新创建的对象。
var bar = new foo()
2. 函数是否通过 call 、 apply (显式绑定)或者硬绑定调用?如果是的话, this 绑定的是
指定的对象。
var bar = foo.call(obj2)
3. 函数是否在某个上下文对象中调用(隐式绑定)?如果是的话, this 绑定的是那个上
下文对象。
var bar = obj1.foo()
4. 如果都不是的话,使用默认绑定。如果在严格模式下,就绑定到 undefined ,否则绑定到
全局对象。
var bar = foo()
就是这样。对于正常的函数调用来说,理解了这些知识你就可以明白 this 的绑定原理了。
不过……凡事总有例外。
间接引用
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
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, 不是 3
箭头函数的绑定无法被修改
当然使用下面的和上面的效果一样
function foo() {
var self = this; // lexical capture of this
setTimeout( function(){
console.log( self.a );
}, 100 );
}
var obj = {
a: 2
};
foo.call( obj ); // 2