作者:Shadeed
譯者:前端小智
來源:dmitripavlutin
有夢想,有乾貨,微信搜尋 【大遷世界】 關注這個在凌晨還在刷碗的刷碗智。
本文 GitHub https://github.com/qq449245884/xiaozhi 已收錄,有一線大廠面試完整考點、資料以及我的系列文章。
在JavaScript中,this
表示函式呼叫上下文。this
難點在於它有一個複雜的行為,這也是面試中經常被考的點。
本文列舉7
個關於this
有趣的面試問題:
- 問題1:變數 vs 屬性
- 問題2:Cat 的名字
- 問題3:延遲打招呼
- 問題4:人工方法
- 問題5:問候和告別
- 問題6:棘手的 length
- 問題7:呼叫引數
問題1:變數 vs 屬性
下面的列印結果是啥:
const object = {
message: 'Hello, World!',
getMessage() {
const message = 'Hello, Earth!';
return this.message;
}
};
console.log(object.getMessage()); // ??
答案:'Hello, World!'
object.getmessage()
是一個方法呼叫,此時的 this
表示 object
。
方法還有一個變數宣告const message = 'Hello, Earth!'
。這個變數都不會影響this.message
的值。
問題2:Cat 的名字
下面程式碼列印什麼:
function Pet(name) {
this.name = name;
this.getName = () => this.name;
}
const cat = new Pet('Fluffy');
console.log(cat.getName()); // What is logged?
const { getName } = cat;
console.log(getName()); // What is logged?
答案:'Fluffy'
和 'Fluffy'
當函式作為建構函式new Pet('Fluffy')
呼叫時,建構函式內部的this
等於構造的物件
Pet
建構函式中的this.name = name
表示式在構造的物件上建立name
屬性。
this.getName = () => this.name
在構造的物件上建立方法getName
。 而且由於使用了箭頭函式,箭頭函式內部的this
值等於外部作用域的this
值, 即 Pet
。
呼叫cat.getName()
以及getName()
會返回表示式this.name
,其計算結果為'Fluffy'
。
問題3:延遲打招呼
下面程式碼列印什麼:
const object = {
message: 'Hello, World!',
logMessage() {
console.log(this.message); // What is logged?
}
};
setTimeout(object.logMessage, 1000);
答案:1秒後,列印 undefined
。
儘管setTimeout()
函式使用object.logMessage
作為回撥,但仍將object.logMessage
用作常規函式,而不是方法。
在常規函式呼叫期間,this
等於全域性物件,即瀏覽器環境中的 window。
這就是為什麼logMessage
方法中的 this.message
等於 window.message
,即undefined
。
問題4:人工方法
如何呼叫logMessage
函式,讓它列印 "Hello, World!"
?
message: 'Hello, World!'
};
function logMessage() {
console.log(this.message); // "Hello, World!"
}
答案:
至少有 3 種方式,可以做到:
message: 'Hello, World!'
};
function logMessage() {
console.log(this.message); // logs 'Hello, World!'
}
// Using func.call() method
logMessage.call(object);
// Using func.apply() method
logMessage.apply(object);
// Creating a bound function
const boundLogMessage = logMessage.bind(object);
boundLogMessage();
問題5:問候和告別
下面程式碼列印什麼:
const object = {
who: 'World',
greet() {
return `Hello, ${this.who}!`;
},
farewell: () => {
return `Goodbye, ${this.who}!`;
}
};
console.log(object.greet()); // What is logged?
console.log(object.farewell()); // What is logged?
答案: 'Hello, World!'
和 'Goodbye, undefined!'
。
當呼叫object.greet()
時,在greet()
方法內部,this
值等於 object,因為greet
是一個常規函式。因此object.greet()
返回'Hello, World!'
。
但是farewell()
是一個箭頭函式,箭頭函式中的this
值總是等於外部作用域中的this
值。
farewell()
的外部作用域是全域性作用域,它是全域性物件。因此object.farewell()
實際上返回'Goodbye, ${window.who}!'
,它的結果為'Goodbye, undefined!'
。
問題6:棘手的 length
下面程式碼列印什麼:
var length = 4;
function callback() {
console.log(this.length); // What is logged?
}
const object = {
length: 5,
method(callback) {
callback();
}
};
object.method(callback, 1, 2);
答案: 4
callback()
是在method()
內部使用常規函式呼叫來呼叫的。由於在常規函式呼叫期間的this
值等於全域性物件,所以this.length
結果為window.length
。。
第一個語句var length = 4
,處於最外層的作用域,在全域性物件 window
上建立一個屬性length
。
問題7:呼叫引數
下面程式碼列印什麼:
var length = 4;
function callback() {
console.log(this.length); // What is logged?
}
const object = {
length: 5,
method() {
arguments[0]();
}
};
object.method(callback, 1, 2);
答案: 3
obj.method(callback, 1, 2)
被呼叫時有3
個引數:callback
, 1
和2
。結果,method()
內部的引數特殊變數是如下結構的陣列類物件:
{
0: callback,
1: 1,
2: 2,
length: 3
}
因為arguments[0]()
是arguments物件上的回撥的方法呼叫,所以回撥內部的引數等於arguments
。 所以 callback()
中的this.length
與arguments.length
相同,即3
。
~ 完,我是小智,我要去刷碗了,我們下期見!
程式碼部署後可能存在的BUG沒法實時知道,事後為了解決這些BUG,花了大量的時間進行log 除錯,這邊順便給大家推薦一個好用的BUG監控工具 Fundebug。
原文:https://dmitripavlutin.com/ja...
交流
有夢想,有乾貨,微信搜尋 【大遷世界】 關注這個在凌晨還在刷碗的刷碗智。
本文 GitHub https://github.com/qq44924588... 已收錄,有一線大廠面試完整考點、資料以及我的系列文章。