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

时间:2009-10-07 05:10:44

标签: javascript

我试图用一个函数来扩展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());

当变量b收到提醒时,我希望看到["a","b","c","d"],而我会看到["a","b","c","d","keys"]

for-in循环似乎包含原型keys()函数。

是否有可能在保持原型的同时避免这种行为,或者我是否应该避免一起进行原型设计?

4 个答案:

答案 0 :(得分:13)

扩展内置插件的乐趣啊。 for..in检查正在迭代的对象的整个原型链。

你需要什么(我相信这是事实上的)是你的循环中hasOwnProperty的检查:

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

hasOwnProperty确保您只获得直接在对象上定义的属性(即在原型链中)。

答案 1 :(得分:4)

对于大多数情况,您应该避免扩展原生Object.prototype。扩展它时,所有对象都会收到这些新属性。

循环对象属性是一项非常常见的任务,正如您所指出的,您遇到了意外行为。

我还没有看到很多人总是在他们的代码中使用hasOwnProperty函数,我会说在“受控环境”下,也许是一个从事项目的独立开发人员,你可以管理这些问题,但是当事情变得更大,并且你有更多的开发人员参与时,这可能会导致很多问题。

如何在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());

答案 2 :(得分:1)

for ... in语句遍历对象由字符串键入的所有可枚举属性(忽略由Symbols键入的属性),包括继承的可枚举属性。 MDN

因此您可以定义不可枚举的属性。

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

答案 3 :(得分:0)

这也有效:

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