简体   繁体   English

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

[英]How to define method in javascript on Array.prototype and Object.prototype so that it doesn't appear in for in loop

I want to define helper methods on the Array.prototype and Object.prototype.我想在 Array.prototype 和 Object.prototype 上定义辅助方法。 My current plan is to do something like:我目前的计划是做这样的事情:

Array.prototype.find = function(testFun) {
   // code to find element in array
};

So that I can do this:这样我就可以做到这一点:

var arr = [1, 2, 3];
var found = arr.find(function(el) { return el > 2; });

It works fine but if I loop over the array in a for in loop the methods appear as values:它工作正常,但如果我在for in循环for in遍历数组,则方法显示为值:

for (var prop in arr) { console.log(prop); }
// prints out:
// 1
// 2
// 3
// find

This will screw up anybody else relying on the for in to just show values (especially on Objects).这会搞砸任何依赖for in来显示值的人(尤其是在对象上)。 The later versions of javascript have .map and .filter functions built into arrays but those don't show up on for in loops.较新版本的 javascript 将 .map 和 .filter 函数内置到数组中,但这些函数不会出现在for in循环中。 How can I create more methods like that which won't show up in a for in loop?如何创建更多不会出现在for in循环中的方法?

It's quite easy: Don't use for-in loops with Arrays .这很简单:不要在 Arrays 中使用for-in 循环 Blame everybody else who does so - here is a nice snippet to tell them during development.责怪其他这样做的人 -这是一个很好的片段,可以在开发过程中告诉他们。

Of course, if one does an enumeration in a generic function and doesn't know whether he gets an array, a plain object or an object with a custom prototype, you can use hasOwnProperty like this:当然,如果在泛型函数中进行枚举并且不知道他得到的是数组、普通对象还是具有自定义原型的对象,则可以像这样使用hasOwnProperty

for (var prop in anyObj )
    if (Object.prototype.hasOwnProperty.call(anyObj, prop))
        // do something

Notice the explicit use of Object.prototype to get the function - there might be objects that overwrite it (especially in data-maps, the value might not even be a function), objects that do not support it or objects that do not inherit from Object.prototype at all.注意显式使用Object.prototype来获取函数 - 可能有对象覆盖它(特别是在数据映射中,值甚至可能不是函数)、不支持它的对象或不继承自的对象根本就是 Object.prototype。 See also here .另请参见此处

Yet, only a script author who is aware of the problem would filter all his for-in-loops - and some only do it because it gets recommended - and does it mostly wrong, he should have used a for-loop array iteration instead.然而,只有知道这个问题的脚本作者才会过滤他所有的 for-in-loops - 有些人只是因为它被推荐而这样做 - 而且它大多是错误的,他应该使用 for-loop array 迭代来代替。 But our problem are those authors who do not know of it.但我们的问题是那些不知道它的作者。

An interesting, but Mozilla-only approach would be overwriting the behavior of enumerations on arrays via __iterate__ , as demonstrated here .一种有趣但仅限 Mozilla 的方法是通过__iterate__覆盖数组上的枚举行为,如下所示

Fortunately, EcmaScript 5.1 allows us setting properties to be non-enumerable .幸运的是,EcmaScript 5.1 允许我们将属性设置为不可枚举 Of course, this is not supported in older browsers, but why bother?当然,这在旧浏览器中是不支持的,但何必呢? We'd need to use es5-shims anyway for all the cool higher-order array stuff :-) Use defineProperty like this:对于所有很酷的高阶数组内容,我们无论如何都需要使用es5-shims :-) 像这样使用defineProperty

Object.defineProperty(Array.prototype, "find", {
    enumerable: false,
    writable: true,
    value: function(testFun) {
        // code to find element in array
    }
});

Depending on your restrictions:根据您的限制:

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

Read more about Object.defineProperty here https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/defineProperty在此处阅读有关Object.defineProperty 的更多信息https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/defineProperty

It's because have to check for hasOwnProperty :这是因为必须检查hasOwnProperty

for (var prop in arr) { 
  if (arr.hasOwnProperty(prop)) { 
    console.log(prop) 
  }
}

Now this logs 1, 2, 3.现在这会记录 1、2、3。

The above answers miss a point:上面的答案忽略了一点:

enumerable ... Defaults to false . enumerable ...默认为 false ( mdn ) ( mdn )

So simply using Object.defineProperty(Array.prototype, 'myFunc' myFunc) instead of Array.prototype.myFunc = myFunc will resolve the issue.所以简单地使用Object.defineProperty(Array.prototype, 'myFunc' myFunc)而不是Array.prototype.myFunc = myFunc就可以解决这个问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM