最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Adding a function to Array.prototype in IE results in it being pushed in to every array as an element - Stack Overf

programmeradmin0浏览0评论

I have added the following polyfill to Array in the beginning of my project:

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;
  };
}

This works perfectly fine in Chrome and Firefox, but on Internet Explorer 11, this function is actually being pushed in every Array as an element of it, and I can even access it like:

var a = [];
a[0]();

This is throwing all sorts of exceptions in IE with functions like .forEach where I am expecting some data and this function is found.

Here's a screenshot from IE's developer tools, in this case, this array should have just 2 elements, instead of 3.

And this is how it should be, from Chrome. In fact, I believe even the actual content is wrong, but i didn't get there yet (it should be an array containing arrays of length 2).

How can JavaScript still behave so wrong in IE11, and how can I correctly add this function to the prototype instead of in every Array instance?

I have added the following polyfill to Array in the beginning of my project:

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;
  };
}

This works perfectly fine in Chrome and Firefox, but on Internet Explorer 11, this function is actually being pushed in every Array as an element of it, and I can even access it like:

var a = [];
a[0]();

This is throwing all sorts of exceptions in IE with functions like .forEach where I am expecting some data and this function is found.

Here's a screenshot from IE's developer tools, in this case, this array should have just 2 elements, instead of 3.

And this is how it should be, from Chrome. In fact, I believe even the actual content is wrong, but i didn't get there yet (it should be an array containing arrays of length 2).

How can JavaScript still behave so wrong in IE11, and how can I correctly add this function to the prototype instead of in every Array instance?

Share Improve this question asked Feb 1, 2016 at 16:12 Bruno FingerBruno Finger 2,5733 gold badges29 silver badges50 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 19

It's not being "pushed" into every array; you added a property to the prototype object, so it's visible and enumerable in every array instance. That's how prototype properties are supposed to work.

It works in Chrome and Firefox because .find() on the prototype in those environments is defined in such a way as to be visible but not enumerable. You can do that in IE by using Object.defineProperty():

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;
    }
  });
}

In addition to property "value", which is clearly the value of the new property, the properties "enumerable" and "configurable" default to false. That means that "find" won't show up in any situation that involves iterating through object properties.

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论