JS的this指向问题

829 阅读3分钟

这是我参与8月更文挑战的第24天,活动详情查看:8月更文挑战

写在前面

在绝大多数情况下,函数的调用方式决定了 this 的值(运行时绑定)。this 不能在执行期间被赋值,并且在每次函数被调用时 this 的值也可能会不同。ES5 引入了 bind 方法来设置函数的 this 值,而不用考虑函数如何被调用的。ES2015 引入了箭头函数,箭头函数不提供自身的 this 绑定(this 的值将保持为闭合词法上下文的值)


var person = {
  firstName: "LiMing",
  lastName : "Li",
  id       : 123,
  fullName : function() {
    return this.firstName + " " + this.lastName;
  }
};

this 是什么?

this是当前执行上下文(global、function 或 eval)的一个属性,在非严格模式下,总是指向一个对象,在严格模式下可以是任意值。

JavaScript this 关键词指的是它所属的对象。

它拥有不同的值,具体取决于它的使用位置:

  • 在方法中,this 指的是所有者对象。
  • 单独的情况下,this 指的是全局对象。
  • 在函数中,this 指的是全局对象。
  • 在函数中,严格模式下,thisundefined。
  • 在事件中,this 指的是接收事件的元素。
  • 像 call() 和 apply() 这样的方法可以将 this 引用到任何对象。

方法中的 this

在对象方法中,this 指的是此方法的“拥有者”。 在本页最上面的例子中,this 指的是 person 对象。 person 对象是 fullName 方法的拥有者。

fullName : function() {
  return this.firstName + " " + this.lastName;
}

单独的 this

在单独使用时,拥有者是全局对象,因此 this 指的是全局对象。

在浏览器窗口中,全局对象是 [object Window]

var x = this;

在严格模式中,如果单独使用,那么 this 指的是全局对象 [object Window]

"use strict";
var x = this;

函数中的 this(默认)

在 JavaScript 函数中,函数的拥有者默认绑定 this

因此,在函数中,this 指的是全局对象 [object Window]

function myFunction() {
  return this;
}

派生类

不像基类的构造函数,派生类的构造函数没有初始的 this 绑定。在构造函数中调用 super() 会生成一个 this 绑定,并相当于执行如下代码,Base为基类:

this = new Base();

注意:在调用 super() 之前引用 this 会抛出错误。

派生类不能在调用 super() 之前返回,除非其构造函数返回的是一个对象,或者根本没有构造函数。

class A {}
class B extends A {}
class C extends A {
  constructor() {
    return {X: 12};
  }
}
class D extends A {
  constructor() {}
}

new B();
new C();
new D(); // ReferenceError

bind方法

ECMAScript 5 引入了 Function.prototype.bind()。调用f.bind(someObject)会创建一个与f具有相同函数体和作用域的函数,但是在这个新函数中,this将永久地被绑定到了bind的第一个参数,无论这个函数是如何被调用的。

箭头函数

在箭头函数中,this与封闭词法环境的this保持一致。在全局代码中,它将被设置为全局对象

注意:如果将this传递给call、bind、或者apply来调用箭头函数,它将被忽略。不过你仍然可以为调用添加参数,不过第一个参数(thisArg)应该设置为null。