先上程式碼:
function foo(){
if (false) {
function foo() {
return 2;
}
}
console.log(foo());
}
foo(); 複製程式碼
以上程式碼會輸出什麼呢?
答案是foo is not a function
以上程式碼可以解釋為如下程式碼:
function foo(){
let foo;
if (false) {
foo = function() {
return 2;
}
}
console.log(foo());
}
foo();
複製程式碼
因為函式宣告在條件為假的if語句裡邊,所以這個時候只是函式宣告的提升,而並沒有初始化該函式,所以此時foo是undefined,把它當做函式呼叫報錯 is not a function
再來看另一個有意思的問題,程式碼如下:
let s = {
a: function() {
console.log(this);
},
b() {
console.log(this);
}
}
let foo = s.a.bind(this),
bar = s.b.bind(this);
console.log(new foo());
console.log(new bar());
複製程式碼
以上程式碼又會輸出什麼呢?
答案是如下:
a {}
a {}
TypeError: bar is not a constructor複製程式碼
這裡涉及到一些new做了什麼,簡單講
1. 建立一個新物件
2. 執行建構函式的程式碼,並將this繫結到新建立的物件
3.將新建立物件的__proto___連線到建構函式的prototype
4.如果建構函式沒有返回一個物件,則返回這個新建立的物件
基於此,也就理解了列印的兩個a一個是執行建構函式程式碼時的console.log,一個是new 操作符的返回值,接下來要思考的是為什麼new bar()的時候報錯了呢?
這是因為ES6屬性名簡寫的函式和箭頭函式都是沒有prototype的,所以會報錯bar不是建構函式,那麼為什麼會這樣設計呢?
這是因為屬性名簡寫的函式作為一個物件的方法,而箭頭函式在宣告的時候就繫結了this,都不會作為建構函式來使用,而且ES6提倡大家放棄對建構函式的使用,而採用Class來實現繼承。
如果有錯誤或者不嚴謹的地方,請給予指正,十分感謝!