2014-06-12 167 views
8

此MDN頁[https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find] 有這樣的填充工具:有人可以解釋這個Array.prototype.find()polyfill?

if (!Array.prototype.find) { 
    Object.defineProperty(Array.prototype, 'find', { 
    enumerable: false, 
    configurable: true, 
    writable: true, 
    value: function(predicate) { 
     if (this == null) { 
     throw new TypeError('Array.prototype.find called on null or undefined'); 
     } 
     if (typeof predicate !== 'function') { 
     throw new TypeError('predicate must be a function'); 
     } 
     var list = Object(this); 
     var length = list.length >>> 0; 
     var thisArg = arguments[1]; 
     var value; 

     for (var i = 0; i < length; i++) { 
     if (i in list) { 
      value = list[i]; 
      if (predicate.call(thisArg, value, i, list)) { 
      return value; 
      } 
     } 
     } 
     return undefined; 
    } 
    }); 
} 

我的問題是什麼,這些線:

var list = Object(this); 
var length = list.length >>> 0; 

因爲this絕對是一個數組(我們正在擴充Array.prototype )爲什麼要確保length是數字,爲什麼使用Object()?

+2

這種填充工具的麻煩是,它需要的Object.defineProperty方法,這在舊版瀏覽器中沒有實現查找功能。 – kennebec

+0

如答案所示; '這個'不能保證是一個數組,你可以在下面的回答中看到'this'可以是什麼(如果你需要比TJ提供的更多信息):http://stackoverflow.com/a/16063711/1641941(under '這個變量') – HMR

回答

10

最基本的答案是,polyfill只是忠實地執行ES6草案規範中算法的步驟1和步驟4(截至5月22日草案的§22.1.3.8)。

1.讓Ø是調用ToObject傳遞這個值作爲參數的結果。

...

4.讓LEN是ToLength(lenValue)。

(其中ToLength基本上是一個轉換成數字。)

而且因爲它可以使用非對象值this現在(通過Function#callFunction#apply,或者乾脆直接調用函數在嚴格模式下),步驟1是有意義的。

因爲this絕對是一個數組(我們正在擴充Array.prototype)爲什麼要確保長度數值,以及爲什麼使用Object()

但我們知道this是一個數組。從目前的ES6草案規範中看到這個註釋:

find函數是有意通用的;它不要求它的this值是一個Array對象。因此可以將其轉換爲其他類型的對象以用作方法。 find函數是否可以成功應用於不是Array的奇特對象取決於實現。

您幾乎可以找到有關分配給原型的所有預定義功能的說明。

例如,你可以,或者通過給它們直接分配給對象或其他原型用於其他的東西:

MyNiftyThing.prototype.find = Array.prototype.find; 

...或通過Function#callFunction#apply

因此,假設我想在arguments對象上使用Array#findarguments當然是數組式樣但不是數組。所以,我可以這樣做:

function foo() { 
    var firstObject = Array.prototype.find.call(arguments, function(val) { 
     return typeof val === "object"; 
    }); 
    // ... 
} 

一個更著名的例子(不涉及find)採用slice到陣列狀物體轉換成數組:

function foo() { 
    // Turn the `arguments` pseudo-array into a real array 
    var args = Array.prototype.slice.call(arguments, 0); 
} 
+0

非常感謝你的一個很好的答案。 –