简体   繁体   English

Javascript 自定义 Array.prototype 干扰 for-in 循环

[英]Javascript custom Array.prototype interfering with for-in loops

I was attempting to extend Javascript's Object type with a function that retrieves all of the property names that are part of that object (basically what PHP's array_keys() function does to associative arrays).我试图用一个函数来扩展 Javascript 的 Object 类型,该函数检索属于该对象的所有属性名称(基本上是 PHP 的array_keys()函数对关联数组所做的)。

Object.prototype.keys = function() {
    var a = [];
    for (var property in this) {
        a.push(property);
    }
    return a;
};

var a = {a:1,b:2,c:3,d:4};
alert(a.toSource());

var b = a.keys();
alert(b.toSource());

When the variable b was alerted, I was expecting to see ["a","b","c","d"] , instead I'm seeing ["a","b","c","d","keys"] .当变量b被警告时,我期待看到["a","b","c","d"] ,而不是我看到["a","b","c","d","keys"]

It appears the for-in loop is including the prototyped keys() functions.看来 for-in 循环包括原型的keys()函数。

Is it possible to avoid this behaviour whilst still prototying, or should I just avoid prototyping all together?是否可以在制作原型的同时避免这种行为,或者我应该避免一起制作原型?

Ahh the joys of extending the built-ins.啊,扩展内置插件的乐趣。 for..in checks up the entire prototype chain of the object being iterated. for..in检查被迭代对象的整个原型链。

What you need (and I believe this is de-facto now) is a check with hasOwnProperty in your loop:你需要的(我相信这是事实上的)是在你的循环中检查hasOwnProperty

for (var property in this) {
    if (this.hasOwnProperty(property)) {
        a.push(property);
    }
}

hasOwnProperty ensures that you only get properties that are directly defined on your object (ie not up the prototype chain). hasOwnProperty确保您只获得直接定义在您的对象上的属性(即不在原型链上)。

For most situations, you should avoid extending the native Object.prototype .在大多数情况下,您应该避免扩展原生Object.prototype When you extend it, ALL objects receive those new properties.当您扩展它时,所有对象都会收到这些新属性。

Looping over an object properties is a really common task, and as you noted, you were experiencing an unexpected behavior.循环对象属性是一项非常常见的任务,正如您所指出的,您遇到了意外行为。

I have not seen many people who always use the hasOwnProperty function in their code, I would say that under "controlled environments", maybe being a solo developer working on a project, you could manage those issues, but when the things get bigger, and you have more developers involved, this can cause a lot of problems.我没有看到很多人总是在他们的代码中使用hasOwnProperty函数,我会说在“受控环境”下,也许作为一个项目的独立开发人员,你可以管理这些问题,但是当事情变得更大时,并且你有更多的开发人员参与,这可能会导致很多问题。

What about making a static function on Object?在 Object 上创建一个静态函数怎么样?

Object.keys = function(obj) {
  var a = [];
  for (var property in obj) {
    if (obj.hasOwnProperty(property)) {
      a.push(property);
    }
  }
  return a;
};

var a = {a:1,b:2,c:3,d:4};
alert(a.toSource());

var b = Object.keys(a);
alert(b.toSource());

The for...in statement iterates over all enumerable properties of an object that are keyed by strings (ignoring ones keyed by Symbols), including inherited enumerable properties. for...in 语句迭代对象的所有以字符串为键的可枚举属性(忽略以符号为键的那些),包括继承的可枚举属性。 MDN MDN

So you can define non-enumerable properties.所以你可以定义不可枚举的属性。

Object.defineProperty(Array.prototype, 'foo', {
  value: 'bar',
  enumerable: false // Defaults to false.
});

const arr = [1,2,3];
for(const k in arr) console.log(k); // 0, 1, 2
console.log(arr.foo); // bar

This also works:这也有效:

var items = [
    {
        id: 1, name: 'Item 1'
    },
    {
        id: 2, name: 'Item 2'
    },
    {
        id: 3, name: 'Item 3'
    }
];
items.forEach(function(item, index) {
    console.log(item);
});

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

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