解释 JavaScript 中 this 的值?

2022年10月9日

💎 加入 E+ 成長計畫 與超過 300+ 位軟體工程師一同在社群中成長,並且獲得更多的軟體工程學習資源

大部分 JavaScript 学习者在学习this 概念时通常觉得一头雾水,许多人觉得是 JavaScript 中最复杂的概念之一,然而this 值是 JavaScript 面试经典题,搞懂 this 值也是战胜面试的第一步。本篇文章会整理出来 this 值的 5 种判断方式,让读者在面试时能轻易掌握这些概念。

在 JavaScript 中,this 的值是动态的,通常会由被呼叫的函式来决定。所以,影响 this 的值不是宣告的时机,关键在于在哪里被调用。

this 值 5 种判断方式

1. 函式调用

当一个函式不是属于一个物件中的方法时,直接作为函式来调用时,this 会指向全局物件,在浏览器中,默认为 Window 。但有一点要注意的是,如果是在严格模式下,thisundefined

如下代码范例,因为是一般函式调用,this 会是指向 Window,所以第一个输出结果是 Window。而因为在全域范围中用 var 定义 name 变数,因此, name 变数也会绑定到 Window 物件上,第二个输出结果也等同于 window.name 的值。 (备注,如果是用 let 定义,并不会绑定在 Window 物件上。)

var name = "John";
function callThis() {
  console.log(this);
  console.log(this.name);
}
callThis();
// Window
// John

2. 物件方法调用

当一个函式是做为一个物件的方法来调用时,this 会指向这个物件。

const john = {
  name: "john",
  callJohn() {
    console.log(`hello, ${this.name}`);
  },
};

john.callJohn(); // hello, john

3. 构造函式调用

当一个函式用 new 关键字调用时,此函式执行前会先创造一个新的物件,this 会指向这个新组成的物件。

如下面代码例子所示,最后呼叫结果为 Apple 。这是因为当构造函式Cellphonenew 调用时,会先创造一个新的物件,让this 会指向这个新物件,=在这个例子中,就印出了这个新物件的 brandApple

function Cellphone(brand) {
  this.brand = brand;
}

Cellphone.prototype.getBrand = function () {
  return this.brand;
};

let newIPhone = new Cellphone("Apple");
let newPixelPhone = new Cellphone("Google");

console.log(newIPhone.getBrand()); // Apple
console.log(newPixelPhone.getBrand()); // Google

4. apply、call、bind 方法调用

我们也可以使用 applycallbind 方法来指定 this 指向的物件。

  • apply 方法接受两个参数,第一个是 this 绑定的对象,第二个会放入要传入函式的数组参数,并执行此新函式。
  • call 方法类似为 apply,唯一不同的地方是,apply 第二个参数是数组,但 call 则是依序放在后面。
  • bind 方法透过传入一个物件和要传入的参数,不同于 applycallbind 不会立即执行此心函式,而是会返回此新函式。
function getBrand(prefix) {
  console.log(prefix + this.brand);
}

let apple = {
  brand: "Apple",
};
let sony = {
  brand: "Sony",
};

getBrand.call(apple, "It's a "); // It's a Apple
getBrand.call(sony, "It's an "); // It's an Sony

5. 箭头函式中的 this

ES6 中介绍了一种新的函式型态 - 箭头函式(arrow function)。但要注意的是,箭头函式并没有属于自己的this 值,箭头函式的this 会从他的外在函式继承,若他的外在函式也同为箭头函示,则回继续往上寻找,直到找到全域环境的预设this 值(例如:浏览器中就是window)。

let getThis = () => this;
console.log(getThis() === window); // true
🧵 如果你想收到最即時的內容更新,可以在 FacebookInstagram 上追蹤我們