一、this 關鍵字的作用
JavaScript 中的 this
關鍵字引用了所在函式正在被呼叫時的物件。在不同的上下文中,this
的指向會發生變化。
在全域性上下文中,this
指向全域性物件(在瀏覽器中是 window
物件,在 Node.js 中是 global
物件)。
在函式中,this
指向呼叫該函式的物件。如果該函式是透過物件的方法呼叫的,那麼 this
指向該物件;如果是透過函式呼叫的,那麼 this
指向全域性物件。
在箭頭函式中,this
繼承自父級作用域中的 this
。
在類的建構函式中,使用 new
關鍵字呼叫類時,this
指向新建立的物件。
例如:
class MyClass {
constructor() {
this.value = 42;
}
}
let obj = new MyClass();
console.log(obj.value); // 42
類的例項方法中的 this 預設指向例項本身,類方法中的 this 預設指向類本身。
例如:
class MyClass {
value = 42;
printValue() {
console.log(this.value);
}
static printValue() {
console.log(this.value);
}
}
let obj = new MyClass();
obj.printValue(); // 42
MyClass.printValue(); // undefined
使用 Object.create
方法建立物件
使用 Object.create
方法建立是一種特殊的呼叫方式。在這種情況下,如果在物件的原型鏈上呼叫函式,則 this
指向該物件。
例如:
let baseObject = { value: 42 };
let obj = Object.create(baseObject);
function printValue() {
console.log(this.value);
}
printValue.call(obj); // 42
這種情況下, obj 的原型鏈上有 value 屬性,所以呼叫 printValue() 方法時, this 指向 obj 物件。
在類中使用箭頭函式
類中使用箭頭函式定義的方法中的 this 指向是繫結的,它指向的是類的例項,而不是類本身。
例如:
class MyClass {
value = 42;
printValue = () => {
console.log(this.value);
}
}
let obj = new MyClass();
obj.printValue(); // 42
箭頭函式的 this
是定義時的 this
,而不是呼叫時的 this
。因此,在類中使用箭頭函式可以避免在方法中使用 bind
來繫結 this
。
在呼叫建構函式時,未使用 new 關鍵字
在這種情況下,this 指向全域性物件。這種情況下不會建立新的物件,而是改變了全域性物件的狀態。
例如:
class MyClass {
constructor() {
this.value = 42;
}
}
let obj = MyClass(); // without new keyword
console.log(obj); // undefined
console.log(value); // 42
因此,在使用建構函式建立物件時,需要確保使用 new 關鍵字來呼叫建構函式,否則可能會導致意外的結果。
在使用建構函式時特別需要注意使用 new 關鍵字來呼叫。
在物件的方法中使用箭頭函式會導致 this 指向問題
例如:
let obj = {
value: 42,
printValue: () => {
console.log(this.value);
}
};
obj.printValue(); // undefined
這種情況下,在 obj 物件的 printValue 方法中使用了箭頭函式,而箭頭函式的 this 指向是定義時的 this,而不是呼叫時的 this。在這種情況下,因為箭頭函式的 this 指向是定義時的 this,所以 this.value 指向的是 undefined,而不是 obj 物件中的 value。
解決這種問題可以使用箭頭函式的父級作用域中的 this,或者使用普通函式來解決。
例如:
let obj = {
value: 42,
printValue: function(){
console.log(this.value);
}
};
obj.printValue(); // 42
或者
let obj = {
value: 42,
printValue: () => {
console.log(obj.value);
}
};
obj.printValue(); // 42
在物件的方法中使用箭頭函式會導致 this 指向問題,需要特別注意。可以使用箭頭函式的父級作用域中的 this 或者普通函式來解決。
總之,JavaScript 中的 this 關鍵字指向的上下文取決於函式的呼叫方式,需要根據不同的場景來選擇合適的方式來改變 this 的指向。
二、如何改變 this 上下文
可以透過 call
, apply
, bind
方法來改變 this
的上下文。
call
和 apply
方法允許您將函式的 this
指向指定的物件,並立即執行該函式。
call
方法的語法格式如下:
functionName.call(thisArg, arg1, arg2, ...);
apply
方法的語法格式如下:
functionName.apply(thisArg, [arg1, arg2, ...]);
bind
方法允許您將函式的 this
指向指定的物件,但不立即執行函式,而是返回一個新函式,可以在將來執行。
let newFunc = functionName.bind(thisArg, arg1, arg2, ...);
例如:
let obj = {value: 42};
function printValue() {
console.log(this.value);
}
printValue.call(obj); // 42
printValue.apply(obj); // 42
let boundFunc = printValue.bind(obj);
boundFunc(); // 42
總之,透過使用 call
, apply
, bind
方法,可以改變函式中的 this
指向,從而在不同的上下文中使用同一個函式。