2011-05-11 50 views
12

在MDC有大量的代碼片段是爲了執行在瀏覽器中新的ECMAScript標準不支持他們,如Array.prototype.map功能支持:爲什麼用這種方式編寫MDC原型函數?

if (!Array.prototype.map) 
{ 
    Array.prototype.map = function(fun /*, thisp */) 
    { 
    "use strict"; 

    if (this === void 0 || this === null) 
     throw new TypeError(); 

    var t = Object(this); 
    var len = t.length >>> 0; 
    if (typeof fun !== "function") 
     throw new TypeError(); 

    var res = new Array(len); 
    var thisp = arguments[1]; 
    for (var i = 0; i < len; i++) 
    { 
     if (i in t) 
     res[i] = fun.call(thisp, t[i], i, t); 
    } 

    return res; 
    }; 
} 

有什麼好處(如果有任何)的使用此功能,而不是

function(fun, thisp) 
{ 
    // same code, just without the "var thisp = arguments[1];" line: 
    "use strict"; 

    if (this === void 0 || this === null) 
    throw new TypeError(); 

    var t = Object(this); 
    var len = t.length >>> 0; 
    if (typeof fun !== "function") 
    throw new TypeError(); 

    var res = new Array(len); 
    for (var i = 0; i < len; i++) 
    { 
    if (i in t) 
     res[i] = fun.call(thisp, t[i], i, t); 
    } 

    return res; 
} 

var t = Object(this);而不是var t = this;var len = t.length >>> 0;而非var len = t.length;

回答

7
var len = t.length >>> 0;  

這被覆蓋得很好this question基本上它確保數字是一個非負32位整數。

爲對象的構造函數:

var t = Object(this); 

如果爲空或未定義,它會返回一個空的對象。從MDC Docs on Object

對象構造函數爲給定值創建一個 對象包裝器。如果 的值爲空或未定義,則其 將創建並返回一個空的 對象,否則,將返回對應於 給定值的 類型的對象。

他們都是快速糾正錯誤的方法。

編輯:我一直在想辦法,太關於thisp部分。我假定使用參數數組是一種確保參數默認爲未定義的方法,但是他們自己也是這樣做的。 Mike Hofer在評論中說得很對。 Mozilla的編碼風格指示可選參數。如果將null或undefined作爲第一個參數傳入,Function.call將默認爲全局。從MDC Docs on Function.call

thisArg: 確定的內 樂趣的值。如果thisArg爲空或未定義,則 這個將是全局對象。 否則,將等於 對象(thisArg)(其是thisArg如果 thisArg已經是一個對象,或者一個 字符串,布爾值,或數量是否thisArg 是 相應類型的原始值)。因此, 總是屬於這種類型的這個 == 「對象」當函數執行時。

+0

謝謝! (但是,你知道那個'function(fun,thisp)'staff嗎?) – 2011-05-11 19:22:30

+0

是的,我剛剛意識到我錯過了,暫時編輯。 – 2011-05-11 19:24:13

+2

'fun(fun/*,thisp * /)'是一個編碼風格*,表示thisp是一個可選參數。當然,'fun'是一個委託函數,後來使用'fun.call'調用,將'thisp'作爲「context」傳遞(即當函數執行時它將成爲'this'的值)。 – 2011-05-11 19:36:19

3

var t = Object(this);

是立足於ES5規範。它明確指出應該將this傳遞給構造函數Object

如果仔細觀察ES5規範中指定的確切算法,那麼Mozilla提供的方法幾乎完全反映了它(它受ES3功能的限制)。這就是這段代碼似乎有一些怪癖的原因。

這裏是ES5規範:

當地圖方法被調用與一個 或兩個參數,採取 以下步驟:

  1. 令O是的結果調用ToObject傳遞這個值作爲參數。
  2. 讓lenValue成爲用參數「length」調用O的[[Get]]內部方法的結果。
  3. 讓len成爲ToUint32(lenValue)。
  4. 如果IsCallable(callbackfn)爲false,則引發TypeError異常。
  5. 如果提供了這個Arg,讓T爲thisArg;否則讓T不確定。
  6. 設A是由新表達式創建的新數組new Array(len)其中Array是具有該名稱的標準內置構造函數,len是len的值。
  7. 令k爲0。
  8. 重複,按住k < len個

    1. 讓PK是的ToString(K)。
    2. 設kPresent是用參數Pk調用O的[[HasProperty]]內部方法的結果。
    3. 如果kPresent爲真,那麼
      • 設置kValue是使用參數Pk調用O的[[Get]]內部方法的結果。
      • 設mappedValue是調用的結果[[調用]其中T callbackfn的內部方法 的該值,並含有kValue,k和O.
      • 調用[[DefineOwnProperty]]內部方法參數列表參數Pk,屬性 描述符{[[Value]]:mappedValue,[[Writable]]:true,[[Enumerable]]:true, [[Configurable]]:true}和false。通過1
  9. 返回A.

令O

  • 增加k爲調用ToObject傳遞該值作爲參數的結果。

  • 注意,一步一明確表示,你應該叫Object(this)

    令lenValue是調用 的[[Get]] O的內部方法與 參數「長度」的結果。

    讓len爲 ToUint32(lenValue)。

    步驟2和3說具體得t.length然後調用ToUint32這是爲>>> 0在這裏實現。

    在說明書中提到的實際簽名是

    Array.prototype.map(callbackfn [,thisArg])

    在上述簽名callbackfn是必需的參數和[ ]是數組可選參數只包含一個thisArg

    Mozilla已經在其function(fun /*, thisp */) {的定義中對此進行了鏡像,以指定thisp是一個可選參數,很明顯,這是從函數簽名而不是從查看代碼的情況。

    相關問題