2014-06-12 118 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

非常感谢你的一个很好的答案。 –