0%

this

js里面this是怎么工作的?
一段代码里面,这些this分别指向什么?为什么呢?

4种this绑定

这4种绑定都是基于被调用点,即函数在哪里被谁调用,this就指向谁。

默认绑定和隐式绑定

直接看 🌰

1
2
3
4
5
6
7
8
9
function foo() { 
console.log(this.bar);
}
var bar = "bar1";
var o2 = {bar: "bar2", foo: foo};
var o3 = {bar: "bar3", foo: foo};
foo(); // "bar1" – 默认绑定
o2.foo(); // "bar2" – 隐式绑定
o3.foo(); // "bar3" – 隐式绑定
显式绑定
1
2
3
4
5
6
7
8
9
function foo() { 
console.log(this.bar);
}
var bar = "bar1";
var obj = {bar: "bar2"};

foo(); // "bar1" 默认绑定
foo.call(obj); // "bar2" 显式绑定,使用obj作为"this"

如果foo是通过call、apply或者bind调用的,那么这种调用就是显式绑定。这种绑定中,this的指向就是这三个函数中传递的第一个参数

关键字new绑定
1
2
3
4
5
6
7
function foo() {
this.baz = "baz";
console.log(this.bar + " " + baz);
}
var bar = "bar";
var baz = new foo();
// undefined, undefined

如果把new这个关键字放在一个函数调用的前面,JS编译器会做这四件事情:

  • 创建一个空对象
  • 将这个对象链接到原型对象上面
  • 把这个对象绑定为this
  • 如果这个函数不返回任何东西,就会默认return this

上面会返回undefined, undefined
this.bar这里的this是window,baz声明了未赋值,所以也是undefined

箭头函数

看两段代码

1
2
3
4
5
6
7
function Person(){
this.age = 0;
setTimeout(function () {
console.log(this.age); // 输出undefined
}, 1000);
}
var p = new Person();
1
2
3
4
5
6
7
function Person(){
this.age = 10;
setTimeout(()=> {
console.log(this.age); // 输出10
}, 1000);
}
var p = new Person();

在上面没有使用箭头函数的例子当中,setTimeout内部的函数是被global调用的,而global没有age这个属性,因此输出undefined。

第二个例子使用了箭头函数,this就会使用lexical scope中的this,就是Person,因此输出10。

绑定优先级

如果多重绑定规格都适用,那么绑定规则的优先级顺序是这样的:

  • 箭头函数
  • 关键字new调
  • 显式绑定
  • 隐式绑定
  • 默认绑定

箭头函数优先级最高,会无视2-5绑定规则。而默认绑定优先级最低,只有其他绑定都不使用的时候,才会使用默认绑定