我想在Array.prototype和Object.prototype上定义辅助方法。我目前的计划是做类似的事情:
Array.prototype.find = function(testFun) {
// code to find element in array
};
所以我可以这样做:
var arr = [1, 2, 3];
var found = arr.find(function(el) { return el > 2; });
它工作正常但如果我在for in
循环中循环遍历数组,则方法显示为值:
for (var prop in arr) { console.log(prop); }
// prints out:
// 1
// 2
// 3
// find
这将使依赖for in
的任何其他人搞砸只显示值(尤其是对象)。更高版本的javascript具有内置于数组中的.map和.filter函数,但这些函数不会显示在for in
循环上。如何创建更多不会出现在for in
循环中的方法?
答案 0 :(得分:21)
这很简单:不要使用for-in loops with Arrays。责怪所有这样做的人 - here is a nice snippet在发展过程中告诉他们。
当然,如果在泛型函数中进行枚举并且不知道他是否获得数组,普通对象或具有自定义原型的对象,则可以使用hasOwnProperty
这样:
for (var prop in anyObj )
if (Object.prototype.hasOwnProperty.call(anyObj, prop))
// do something
注意显式使用Object.prototype
来获取函数 - 可能有对象覆盖它(特别是在数据映射中,值可能不是函数),do not support it或here或根本不从Object.prototype继承的对象。另请参阅it gets recommended。
然而,只有知道这个问题的脚本作者会过滤掉他所有的for-in-loops - 而有些只是因为__iterate__
而这样做 - 并且大部分是错误的,他应该使用for-而是循环数组迭代。但我们的问题是那些不了解它的作者。
一个有趣的,但仅限Mozilla的方法是通过demonstrated here覆盖数组上的枚举行为,es5-shims。
幸运的是,EcmaScript 5.1允许我们将属性设置为不可枚举。当然,旧浏览器不支持此功能,但为什么要这么麻烦?无论如何,我们需要使用defineProperty
来处理所有很酷的高阶数组:-)像这样使用{{3}}:
Object.defineProperty(Array.prototype, "find", {
enumerable: false,
writable: true,
value: function(testFun) {
// code to find element in array
}
});
答案 1 :(得分:5)
取决于您的限制:
// In EcmaScript 5 specs and browsers that support it you can use the Object.defineProperty
// to make it not enumerable set the enumerable property to false
Object.defineProperty(Array.prototype, 'find', {
enumerable: false, // this will make it not iterable
get: function(testFun) {
// code to find element in array
};
});
在此处详细了解 Object.defineProperty https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/defineProperty
答案 2 :(得分:0)
这是因为必须检查hasOwnProperty
:
for (var prop in arr) {
if (arr.hasOwnProperty(prop)) {
console.log(prop)
}
}
现在记录1,2,3。
答案 3 :(得分:0)
以上答案遗漏了一点:
可枚举... 默认为false 。 (mdn)
因此,只需使用Object.defineProperty(Array.prototype, 'myFunc' myFunc)
而不是Array.prototype.myFunc = myFunc
就可以解决问题。