forEach中提供了数组原型

时间:2014-10-10 14:49:31

标签: javascript arrays prototype

我从MDN

获得了Array.find()的填充

我正在测试的浏览器不支持它,因此polyfill运行并按预期运行。然而,我拥有的插件是foreach我传递的数组,其中的最后一个元素是函数find

为什么会这样?

当我在Chrome的DevTools中检查数组时,我得到以下内容。

if (!Array.find) {
   $('<h5>This browser doesnt support Array.find</h5>').appendTo('body');
}

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

var someArray = [{name: 'something'}, {name: 'something else'}];

someArray.forEach(function (item, index) {
  $('<h4>'+ item.name +'</h4>').appendTo('body');
});

var extended = $.extend({}, [], someArray);

$.each(extended, function (index, item) { 
  $('<h4>'+ item.name +'</h4>').appendTo('body');
});

if (extended.find) {
  $("<div>Notice that we now have in extended the function find<div>").appendTo('body');
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

enter image description here

请注意,find中的__proto__是比其他proto更深的粉红色。

有什么想法吗?

2 个答案:

答案 0 :(得分:4)

您的foreach扩展程序正在检查密钥,但不检查它们是否是对象的自有属性。也就是说,这段代码:

Array.prototype.x = 3;
var test = [1];
for (var key in test) {
    console.log(key); 
}

...将同时记录0x,因为x[]中的可枚举密钥,它不是[]的自有属性。要解决此问题,您可以修补foreach代码以仅检查自己的属性:

Array.prototype.x = 3;
var test = [1];
for (var key in test) {
    if (test.hasOwnProperty(key)) {
        console.log(key); 
    }
}

或者您可以更改将键放在原型上的方式,这样就像原型上的其他键一样,它不是可枚举的。修改后的poyfill将是:

(function () { // scope bracket; hides `find` from global scope.
    function find(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), length = list.length >>> 0, thisArg = arguments[1], value, i;
        for (i = 0; i < length; i++) {
            value = list[i];
            if (predicate.call(thisArg, value, i, list)) {
                    return value;
            }
        }
        return undefined;
    };
    if (!Array.prototype.find) {
        if (Object.defineProperty) {
            Object.defineProperty(Array.prototype, 'find', {value: find, enumerable: false});
        } else {
            Array.prototype.find = find;
        }
    }
} ());

但是,如果您的浏览器不支持Array.prototype.find,则有可能它不支持Object.defineProperty,让您回到原来的位置。然后,您需要希望它不是那么老,以至于它缺少.hasOwnProperty()测试,并且您需要修改foreach函数。 (Array.prototype.find()函数是ECMAScript 6草案的一部分; Object.defineProperty()在ECMAScript 5.1中标准化,而Object.prototype.hasOwnProperty()是ECMAScript 3. ES5.1在2011年发布,只要您的浏览器只有几年的历史,上面应该适合你 - 特别是如果你使用当前的Opera或IE,那些还没有新的ES6 .find(),但是他们有Object.defineProperty

答案 1 :(得分:2)

谷歌浏览器会增加添加到它的方法,但不是已经加入的方法。

执行此操作

Array.prototype.hi  = function() {}

然后再做

console.log(Array.prototype);

您会看到hi变暗。由于find尚未成为Array.prototype的一部分,但在执行代码后变为一个,因此它变暗,与hi变暗的方式相同。