this
是 JavaScript 中的一個關鍵字,它的值通常根據呼叫方式決定。箭頭函式例外,它在定義時就繼承外層的 this。
呼叫方式/情境 | this 指向(在瀏覽器中) | 備註 |
---|---|---|
全域(非嚴格模式) | window |
Node.js 中為 global |
全域(嚴格模式) | undefined |
|
函式直接呼叫 | window (非嚴格) / undefined (嚴格) |
|
物件方法呼叫 | 呼叫該方法的物件 | 例如 obj.method() |
constructor 中 (new ) |
新建立的實體物件 | this 指向 new 出來的物件 |
class 中的 method | 該 class 實體 | 類似一般物件的行為 |
callback 函式(一般函式) | window (非嚴格) / undefined (嚴格) |
例如:[1,2,3].forEach(function(){}) |
setTimeout/setInterval | window |
Node.js 中為 Timeout (但非預期) |
IIFE(立即執行函式) | window (非嚴格) / undefined (嚴格) |
箭頭函式永遠不會自己創造 this,它只會繼承「定義當下」的外層 this
this
行為總表定義位置 / 外層 this |
箭頭函式的 this 指向(在瀏覽器中) |
備註 |
---|---|---|
全域 | window |
若在全域中定義箭頭函式 |
class 中的 method | 該 class 實體 | this 繼承外層 class context,例如 constructor 中定義箭頭函式 |
setTimeout / setInterval 中定義 | 外層 this |
例如在物件內使用箭頭函式當定時器 callback,會指向物件本身 |
callback 函式 | 外層 this |
常見於 class 或物件中使用 forEach 來處理資料時 |
IIFE(立即執行函式) | 外層 this |
箭頭函式沒有自己的作用域,直接吃外面那層 |
🧠 箭頭函式的 this 核心原則:
箭頭函式永遠不會自己創造this
,它只會繼承「定義當下」的外層this
。
var myName = "小明";
console.log(this === window); // true(在瀏覽器中)
console.log(this.myName); // "小明"
"use strict";
var myName = "小明";
function fn() {
console.log(this); // undefined
}
fn();
var myName = "小明";
function sayName() {
console.log(this); // window(非嚴格)
console.log(this.myName); // "小明"
}
sayName();
var myName = "小明";
(function () {
console.log(this); // window(非嚴格)
})();
(() => {
console.log(this); // window,箭頭函式繼承外層的 this
})();
const family = {
myName: "小明家",
callName() {
console.log(this.myName); // "小明家"
},
};
family.callName();
const family = {
myName: "小明家",
ming: {
myName: "小明",
callName() {
console.log(this.myName); // "小明"
},
},
};
family.ming.callName();
class Person {
constructor(name) {
this.name = name;
console.log(this);// this 指向 new 出來的物件
}
sayHi() {
console.log("Hi, I am", this.name); // this 指向呼叫 sayHi() 的實例物件
}
}
const p1 = new Person("小明");
p1.sayHi(); // this === p1 → "Hi, I am 小明"
[1, 2, 3].forEach(function () {
console.log(this); // window(非嚴格)
});
"use strict";
const arr = [1, 2, 3];
arr.forEach(function (item) {
console.log(this); // ❗️在嚴格模式下,這裡的 this 是 undefined
});
🔹 普通函式寫法(需要保存 this)
const component = {
text: "Hello",
getData() {
const that = this;
setTimeout(function () {
that.text = "Hi";
console.log(that.text); // "Hi"
});
},
};
component.getData();
🔹 箭頭函式寫法(自動繼承外層 this)
const person = {
name: "小明",
sayHi() {
setTimeout(() => {
console.log(this.name); // "小明"
}, 1000);
},
};
person.sayHi();
window.myName = "全域的小明";
const family = {
myName: "小明家",
callName: () => {
console.log(this.myName); // "全域的小明"(繼承外層的 this = window)
},
};
family.callName();
window.myName = "全域的小明";
const family = {
myName: "小明家",
callName: function () {
(() => {
console.log(this.myName); // "小明家"
})();
},
};
family.callName();
const component = {
text: "預設文字",
el: document.getElementById("root"),
getData() {
const that = this;
setTimeout(function () {
that.text = "已更新";
that.render();
});
},
init() {
this.getData();
},
render() {
this.el.innerText = this.text;
},
};
const component2 = {
...component,
el: document.getElementById("root2"),
};
component.init();
component2.init();