在IE中向Array.prototype添加函数会导致它作为元素被推入到每个数组中

Bru*_*ger 8 javascript internet-explorer-11

Array在项目的开头添加了以下polyfill :

if (!Array.prototype.find) {
  Array.prototype.find = 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++) {
      value = list[i];
      if (predicate.call(thisArg, value, i, list)) {
        return value;
      }
    }
    return undefined;
  };
}
Run Code Online (Sandbox Code Playgroud)

这部作品在Chrome和Firefox完美的罚款,但在Internet Explorer 11,此功能实际上是被推向每一个Array作为它的一个元素,我甚至可以访问它,如:

var a = [];
a[0]();
Run Code Online (Sandbox Code Playgroud)

这是在IE中抛出各种异常的函数,比如.forEach我期待一些数据并且找到了这个函数.

这是IE开发人员工具的截图,在这种情况下,这个数组应该只有2个元素,而不是3个.

IE  - 错了

这就是它应该如何,来自Chrome.事实上,我相信即使实际内容是错误的,但我还没到达那里(它应该是一个包含长度为2的数组的数组).

Chrome  - 正确

如何在IE11中JavaScript仍然表现得如此错误,我怎样才能正确地将此函数添加到prototype每个Array实例中?

Poi*_*nty 18

它没有被"推入"每个阵列; 您向原型对象添加了一个属性,因此它在每个数组实例中都是可见的可枚举的.这就是原型属性应该如何工作的原因.

它适用于Chrome和Firefox,因为.find()在这些环境中的原型是以可见不可 枚举的方式定义的.您可以使用Object.defineProperty()以下方法在IE中执行此操作:

if (!Array.prototype.find) {
  Object.defineProperty(Array.prototype, "find", {
    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++) {
        value = list[i];
        if (predicate.call(thisArg, value, i, list)) {
          return value;
        }
      }
      return undefined;
    }
  });
}
Run Code Online (Sandbox Code Playgroud)

除了属性"value",它显然是新属性的值,属性"enumerable"和"configure"默认为false.这意味着在任何涉及迭代对象属性的情况下都不会出现"find".