我试图用一个函数来扩展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()
函数。
是否有可能在保持原型的同时避免这种行为,或者我是否应该避免一起进行原型设计?
答案 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);
});