解释 JavaScript 中 this 的值?
2022年10月9日
大部分 JavaScript 学习者在学习this
概念时通常觉得一头雾水,许多人觉得是 JavaScript 中最复杂的概念之一,然而this
值是 JavaScript 面试经典题,搞懂 this 值也是战胜面试的第一步。本篇文章会整理出来 this
值的 5 种判断方式,让读者在面试时能轻易掌握这些概念。
在 JavaScript 中,this
的值是动态的,通常会由被呼叫的函式来决定。所以,影响 this
的值不是宣告的时机,关键在于在哪里被调用。
this 值 5 种判断方式
1. 函式调用
当一个函式不是属于一个物件中的方法时,直接作为函式来调用时,this
会指向全局物件,在浏览器中,默认为 Window
。但有一点要注意的是,如果是在严格模式下,this
为 undefined
。
如下代码范例,因为是一般函式调用,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
。这是因为当构造函式Cellphone
被new
调用时,会先创造一个新的物件,让this
会指向这个新物件,=在这个例子中,就印出了这个新物件的 brand
是Apple
。
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 方法调用
我们也可以使用 apply
、call
、bind
方法来指定 this
指向的物件。
apply
方法接受两个参数,第一个是 this 绑定的对象,第二个会放入要传入函式的数组参数,并执行此新函式。call
方法类似为apply
,唯一不同的地方是,apply
第二个参数是数组,但call
则是依序放在后面。bind
方法透过传入一个物件和要传入的参数,不同于apply
和call
,bind
不会立即执行此心函式,而是会返回此新函式。
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