JavaScript:深入了解This的指向與應用
2.0k 字,約 2 分鐘
文章目錄
🌟 JavaScript this 指向跟調用方式相關
一個函式中包含多少參數
var a = '全域'
function fn(params) {
console.log(params, this, window, arguments);
}
fn(100, 200, 300)
- 每個 Function 都擁有params及arguments
- params(參數):參數是函式定義中所列出的變數
- 100
- arguments(引數):引數是當我們呼叫函式時傳遞給它的值
- 100, 200, 300
- 這個是類陣列(Array-like):意思就是他不是真的陣列,有一些方法他並無法使用,雖然他可以查看長度,以及變更參數的值,但是他不是純陣列。
- this(隱含的引數):根據調用的方式指向的位置不同(這邊是全域變數也就是 window)
- params(參數):參數是函式定義中所列出的變數
- window:預設的全域變數。
- 接著讓我們來了解不同情況的 this 的指向(以調用的方式為主)
- 這邊 this 是 callSomeone 的孩子,本身自己調用函式的情況下 this 會指向全域(window)變數,也就是全域變數的 someone。
var someone = '全域';
function callSomeone() {
console.log(this.someone);
}
callSomeone();
顯示如下:
全域
案例 1.傳統函式 this 指向
- 當前案例 this 是 callSomeone 的小孩。
- 調用的方式改成透過 obj 去調用這個 callSome,這時候 this 會改指向前面的這個怪叔叔,也就是 obj,所以這邊的 this 已經不是 window,已經改變成 obj,自然 this.someone 就會變成 obj 裡面的 someone。
var someone = '搗蛋鬼'
var obj = {
someone: '物件',
callSomeone() {
console.log(this.someone);
}
}
obj.callSomeone();
顯示如下:
物件
案例 2.引用傳統函式 this 指向(小小變形一下)
- 雖然原本定義在 obj 裡面的 function 變成引用外面的 function,但調用的方式依然是 obj2.callSomeone(),傳統函式的情況大多符合這種規則。
var someone = '全域';
function callSomeone() {
console.log(this.someone);
}
var obj2 = {
someone: '物件2',
callSomeone
}
obj2.callSomeone();
顯示如下:
物件2
案例 3.夾帶兩層函式的 this 指向
- 這邊可以看到 wrapObj.callSomeone()這個是由 wrapObj 調用,因此 this 會指向 wrapObj 這個物件,自然就會將 this.someone 定義成外層物件。
- 而 wrapObj.innerObj.callSomeone()調用的人改變成 innderObj,因此調用的 this.someone 將會定義成 innerObj 裡面的內層物件。
var someone = '搗蛋鬼';
function callSomeone() {
console.log(this.someone);
}
var wrapObj = {
someone: '外層物件',
callSomeone,
innerObj: {
someone: '內層物件',
callSomeone,
}
}
wrapObj.callSomeone()
wrapObj.innerObj.callSomeone();
顯示如下:
外層物件
內層物件
特殊案例 1.間接使用 this 函式
- 我們來看看特別一些的案例,記清楚剛剛說過 this 只取決於調用他的人是誰,callSomeone 前面並沒有人使用它,因此他的 this 會指向全域(陷阱題)。
var someone = '搗蛋鬼';
function callSomeone() {
console.log(this.someone);
}
var obj3 = {
someone: '物件 3',
fn() {
callSomeone();
}
}
obj3.fn();
顯示如下:
搗蛋鬼
特殊案例 2.setTimeout 回調函式
- 大部分傳統函式的情況下,遇到回調函式,this 會指向全域變數,因此 this.someone 會變成搗蛋鬼。
var someone = '搗蛋鬼';
var obj4 = {
someone: '物件 4',
fn() {
setTimeout(function () {
console.log(this.someone);
});
}
}
obj4.fn();
顯示如下:
搗蛋鬼
留言
留言使用 GitHub 帳號登入(Giscus),留言會存在 GitHub Discussions。