記錄一些有趣的題目,拆解其中的原理
題目內容
請寫出輸出內容
var fullname='aaa';
var obj = {
fullname: 'bbb',
getFullName: () => this.fullname,
prop:{
fullname: 'ccc',
getFullName: function(){
return this.fullname;
}
}
};
console.log(obj.prop.getFullName());
console.log(obj.getFullName());
var func1 = obj.prop.getFullName;
console.log(func1());
var func2 = obj.getFullName;
console.log(func2());
複製程式碼
題目分析
很顯然,這道題就是在考察this繫結的問題。來複習一下關於this的知識點
在絕大多數情況下,函式的呼叫方式決定了this的值。this不能在執行期間被賦值,並且在每次函式被呼叫時this的值也可能會不同。
簡單說就是this會指向呼叫者的物件
so easy,答案很簡單
第一,呼叫者是obj.prop, 應該是ccc
第二和第四,因為繫結了obj,所以都是bbb
第三,呼叫者是window,所以是aaa
'ccc', 'bbb', 'aaa', 'bbb'
複製程式碼
等等,是不是太順利了,果然翻開答案一看
'ccc', 'aaa', 'aaa', 'aaa'
複製程式碼
誒?箭頭函式不是繫結父級作用域的麼,難道出現了幻覺?為什麼會繫結到window上呢?
先查一下MDN,在箭頭函式中,this與封閉詞法環境的this保持一致
那好,先來查一下封閉詞法環境(enclosing lexical context)是什麼東東。
A function serves as a closure in JavaScript, and thus creates a scope, so that (for example) a variable defined exclusively within the function cannot be accessed from outside the function or within other functions
函式在JavaScript中被解析為一個閉包,從而建立了一個作用域,使其在一個函式內定義的變數不能從函式外訪問或從其他函式內訪問。
那麼難道是說只有函式才能建立作用域,其他變數都是不行的麼?我們來驗證一下
var fullname = "aaa";
var obj = {
fullname: "bbb",
prop: {
fullname: "ccc",
getFullName: () => this.fullname
}
};
console.log(obj.prop.getFullName());
function A() {
this.fullname = 'bbb';
}
var a = new A();
a.getFullName = () => this.fullname;
console.log(a.getFullName());
// 'aaa' 'aaa'
複製程式碼
結果表明,不管是字面量還是new出來的物件都是無法建立作用域的
那麼問題來了this的作用域在會隨著上層函式的作用域變化而變化麼?讓我們來驗證一下
var fullname='aaa';
var obj = {
fullname: 'bbb',
getFullName: function () {
return (() => this.fullname)()
}
};
console.log(obj.getFullName());
var getFullName = obj.getFullName;
console.log(getFullName());
// 'bbb', 'aaa'
複製程式碼
答案是肯定的。好了,新知識get到手。
總結
箭頭函式的this指向父級函式的this,物件無法建立作用域
最後來複習一下關於this的相關知識,這裡祭出MDN大法
- 在全域性執行環境中(在任何函式體外部)this 都指向全域性物件。
- 在函式內部,this的值取決於函式被呼叫的方式。
- 當函式作為物件裡的方法被呼叫時,它們的 this 是呼叫該函式的物件。
- 當一個函式用作建構函式時(使用new關鍵字),它的this被繫結到正在構造的新物件。
- 當函式被用作事件處理函式時,它的this指向觸發事件的元素。
- 當程式碼被內聯on-event 處理函式呼叫時,它的this指向監聽器所在的DOM元素:
- 在箭頭函式中,this與封閉詞法環境的this保持一致