2017-08-23 113 views
3

下面的代碼失敗:爲什麼傳遞函數引用失敗,而使用函數聲明不是?

array.map(String.prototype.toLowerCase) 

拋出Uncaught TypeError: String.prototype.toLowerCase called on null or undefined。確實,this沒有設置,我明白了。

但是,什麼是奇怪的是,下面的代碼返回空字符串數組沒有失敗:

array.map((s) => String.prototype.toLowerCase(s)) 

任何想法,爲什麼? 請注意,我知道這不是具有小寫字符串數組的方式。我只是想知道爲什麼這兩種方法表現不同。

換句話說,.map(String.prototype.toLowerCase).map((s) => String.prototype.toLowerCase(s))之間的區別是什麼?我認爲是相同的,但很明顯,它的行爲有所不同。請注意,在這裏,String.prototype.toLowerCase可以被任何東西取代。

回答

2

是什麼.map(String.prototype.toLowerCase).map((s) => String.prototype.toLowerCase(s))

之間的區別對於第一種情況,當你得到函數的對象(String.prototype.toLowerCase)你失去了你的背景之外,所以你的上下文爲null,並且map試圖調用在null or undefined。使用第一種解決方案,您無法獲得理想的結果,因爲您需要將上下文傳遞給toLowerCase函數,該函數必須是陣列中的每個項目,但是您沒有得到,即每個項目的數組

對於需要傳遞這是itemString.prototype.toLowerCase經由call功能的第二殼體上下文

var array = ['ASD', 'BSD']; 
 

 
var lowered = array.map(item => String.prototype.toLowerCase.call(item)); 
 

 
console.log(lowered);

+0

這將無法工作既不併沒有真正回答這個問題。換句話說,'.map(String.prototype.toLowerCase)'和'.map((s)=> String.prototype.toLowerCase(s))'有什麼區別?我認爲是相同的,但很明顯,它的行爲有所不同。 – sp00m

+0

查看編輯部分 –

+0

我認爲這不完全正確,但它幫助我找出答案,所以謝謝;)基本上,國際海事組織,第一個有這個設置爲undefined,而第二個設置爲String.prototype。看到我自己的答案。 – sp00m

1

.map(String.prototype.toLowerCase) and .map((s) => String.prototype.toLowerCase(s))差異性之探源是.map((s) => String.prototype.toLowerCase(s))需要的箭頭函數,它是一個匿名函數。根據箭頭函數的定義 「箭頭函數表達式的語法比函數表達式短,並且不綁定它自己的this,arguments,super或new.target。」 「箭頭函數不會創建它自己的this ,使用封閉執行上下文的這個值。 使用.map(String.prototype.toLowerCase)將無法​​正常工作,因爲您沒有將任何執行上下文傳遞給它,但它正在尋找要執行的上下文。 例如在下面的代碼

function Person(){ 
    this.age = 0; 

    setInterval(() => { 
    this.age++; // |this| properly refers to the person object 
    }, 1000); 
} 

var p = new Person(); 

請檢查該鏈接 https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions/Arrow_functions

+0

感謝您的回答,但我認爲您錯誤地使用了「封閉執行上下文的這個值」。基本上,國際海事組織,首先有這個設置未定義,而第二個有這個設置爲String.prototype。看到我自己的答案。 – sp00m

+0

你是對的,但我的意見與我在下面提供的示例代碼有關,其中'this'是指Person類對象而不是全局窗口對象 – Niladri

0

我想我得到了它最後:

  • 第一個具有this設置爲undefined,相當於:
.map((s) => String.prototype.toLowerCase.call(undefined, s)) 
  • ,而第二個具有this設置爲String.prototype,相當於:現在
.map((s) => String.prototype.toLowerCase.call(String.prototype, s)) 

,問題是,爲什麼String.prototype.toLowerCase()將返回一個空字符串......但是,這值得另一個問題:)

2

第二種方法array.map((s) => String.prototype.toLowerCase(s))不會拋出錯誤,因爲toLowerCase沒有脫離上下文,即該方法仍然有String.prototype作爲其接收者。

String.prototype.toLowerCase(s))返回一個空字符串,因爲參數s被丟棄。 toLowerCase代替它的接收對象的值。接收對象是String.protoype。爲了得到實際的字符串,原型必須轉換爲字符串。這發生在String.prototype.toString方法中,該方法的計算結果爲""。因此String.prototype.toLowerCase(s))評估爲""

您可以通過改變toString方法來驗證此行爲:

String.prototype.toString =() => "FOO"; 
 
console.log(String.prototype.toLowerCase()); // "foo"

相關問題