如何在Array.prototype和Object.prototype上的javascript中定义方法,以便它不会出现在for循环中

时间:2012-11-08 19:31:05

标签: javascript function

我想在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循环中的方法?

4 个答案:

答案 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 ithere或根本不从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就可以解决问题。