我从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>
请注意,find
中的__proto__
是比其他proto
更深的粉红色。
有什么想法吗?
答案 0 :(得分:4)
您的foreach
扩展程序正在检查密钥,但不检查它们是否是对象的自有属性。也就是说,这段代码:
Array.prototype.x = 3;
var test = [1];
for (var key in test) {
console.log(key);
}
...将同时记录0
和x
,因为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
变暗的方式相同。