谁能解释一下这个Array.prototype.find()polyfill?

M.J*_*edy 8 javascript arrays

在这个MDN页面上[ https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/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;
    }
  });
}
Run Code Online (Sandbox Code Playgroud)

我的问题是这些行是什么:

var list = Object(this);
var length = list.length >>> 0;
Run Code Online (Sandbox Code Playgroud)

因为this肯定是一个数组(我们正在扩充Array.prototype)所以为什么要确保length是数字,为什么使用Object()?

T.J*_*der 11

根本的答案是,polyfill只是忠实地实现了ES6草案规范(截至5月22日草案的§22.1.3.8)中算法的第1步和第4步.

1.设O是调用ToObject传递值作为参数的结果.

...

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;
Run Code Online (Sandbox Code Playgroud)

......或通过Function#callFunction#apply.

所以假设我想Array#find在一个arguments对象上使用.arguments当然,它是类似数组但不是数组.所以我可能这样做:

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

一个更着名的例子(不涉及find)slice用于将类似数组的对象转换为数组:

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