再來兩個小問題

王振宇發表於2019-03-14

先上程式碼:

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來實現繼承。

如果有錯誤或者不嚴謹的地方,請給予指正,十分感謝!


相關文章