this指向问题

42 阅读2分钟

前言

this 关键字是javascript中最复杂的机制之一。它是一个很特别的关键字,被自动定义在所有函数的作用域中。但是即使是非常有经验的javascript开发者也很难说清楚它到底指向什么。--借鉴于你《不知道的jvascript上卷》
希望能帮助诸位对this有个清晰的认识。

对this的误解

1、指向自身。人们通常把this理解成指向函数自身

function demo1() {
  const num = 5;
  // this.num等于5是错误的。this指向window
  console.log(this.num);
}

demo1();

2、指向函数的作用域

function demo1() {
  const num = 5;

  this.demo2();
}

function demo2() {
  // this并不指向当前词法作用域
  console.log(this.num);
}

demo1();

绑定规则

函数的this指向是由函数的调用位置决定的

1、默认绑定:作为普通函数调用this指向全局对象(window)

可以看作把这条规则无法应用于其他规则时的默认规则。需要注意的是如果使用严格,则不能绑定到全局对象,this会绑定到undefined。

var num = 1;
function demo() {
  console.log(this.num);
}

demo(); // 1

2、隐式绑定:作为对象的方法调用

当函数调用的位置有上下文对象,或者某个对象拥有函数的指针。对象obj拥有foo函数的指针,当调用obj.foo()时,该函数的this就被绑定到了obj这个上下文对象上。

const obj = {
  a: 8,
  getA: function () {
    console.log("getA:", this.a);
  },
  foo,
};

function foo() {
  console.log("foo:", this.a);
}

obj.getA(); // 8
obj.foo();  // 8

3、new绑定:构造函数调用

参考:new 运算符 - JavaScript | MDN (mozilla.org)

function foo(a) {
  this.a = a;
}

const bar = new foo(10);
console.log(bar.a); // 10

4、显示绑定:apply和call

applycall用法一致。
apply(thisArg, argsArray)thisArg在 func 函数运行时使用的 thisargsArray一个数组或者类数组对象,其中的数组元素将作为单独的参数传给 func 函数。如果该参数的值为nullundefined,则表示不需要传入任何参数
call(thisArg, arg1, arg2, ...)thisArg同上;arg1, arg2, ...指定的参数列表

var a = 10;
var obj = {
  a: 1,
};

function foo() {
  console.log(this.a);
}

foo.apply(obj, null); // 1