- 什么是this
this是在函数调用时建立的一个绑定,this不是在编写的时候绑定的,而是在运行时绑定的,他依赖于函数调用的上下文关系,this绑定与他的调用点有关,而与函数的声明位置无关。
- 调用点:函数在代码中被调用的位置。
- 3种this绑定的规则
1 默认绑定:这种绑定规则是在没有其他规则时使用,常见有:独立函数调用(如下)
function foo(){ console.log( this.a ); } var a = 2; foo();// 2 此时foo是在全局中被调用的,所以this指向了全局对象,this.a相当于window.a,故输出2
2 隐含绑定
function foo() { console.log( this.a ); } var obj = { a: 2, foo: foo }; obj.foo(); // 2 this此时指向obj,所以this.a相当于obj.a
隐含绑定丢失
function foo() { console.log( this.a ); } function doFoo(fn) { // `fn` 只不过`foo`的另一个引用 fn(); // <-- 调用点! } var obj = { a: 2, foo: foo }; var a = "global"; // `a`也是一个全局对象的属性 doFoo( obj.foo ); // "global",doFoo()调用时this指向全局,所以指向this.a是会调用全局属性a而不是obj中的a
3 明确绑定 使用call apply bind(硬绑定,解决this丢失的问题)
function foo() { console.log( this.a ); } var obj = { a: 2 }; var a = "global"; foo.call( obj ); // 2
- 绑定的优先级 明确绑定 > 隐含绑定 > 默认绑定
- 绑定类型判定
函数是否用call apply bind调用,是就是明确绑定 -> 函数环境对象调用的话就是隐含绑定 -> 默认绑定
- 特例
明确绑定中的参数this的指向为null和undefined的时候采用默认绑定
间接引用:
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()
。根据上面的结果,默认绑定 规则适用。
箭头函数 :一旦绑定就不会被覆盖
function foo() { // 返回一个arrow function return (a) => { // 这里的`this`是词法上从`foo()`采用 console.log( this.a ); }; } var obj1 = { a: 2 }; var obj2 = { a: 3 }; var bar = foo.call( obj1 ); //bar是return的箭头函数的引用,已经指向obj1,此后不在覆盖 bar.call( obj2 ); // 2, 不是3!