JavaScript的for-in循环是否遍历方法?

8
在 yuiblog 上的一篇 文章 中,Douglas Crockford 表示 for in 语句将遍历对象的方法。为什么以下代码没有产生 ["a", "b", "c", "d", "toString"]?.toString() 和其他方法不是 my_obj 的成员吗?
Object.prototype.toString = function(){return 'abc'}
Object.prototype.d = 4;

my_obj = {
    'a':1,
    'b':2,
    'c':3
}

a = []
for (var key in my_obj) {
    a.push(key)
}

console.log(a) // prints ["a", "b", "c", "d"]
2个回答

12

所有用户定义的属性都是可枚举的,包括从原型继承而来的属性。内置的本地属性则不是。 toString()就是其中之一。请参见此处:https://developer.mozilla.org/En/Core_JavaScript_1.5_Reference/Statements/For...in

编辑:我对“然而,循环将遍历所有用户定义的属性(包括任何覆盖内置属性的属性)”的理解是直接在对象中被覆盖的属性变得可枚举。并非原型本身的覆盖。这意味着:

var my_obj = {a: 1, b: 2, c: 3};
my_obj.toString = function() {return 'abc';};

a = []
for (var key in my_obj) {
    a.push(key)
}

console.log(a) // prints ["a", "b", "c", "toString"]

2
是的,Object.prototype.toString.propertyIsEnumerable() == false - Christian C. Salvadó
从您提供的文档中可以看到:“for...in循环不会迭代内置属性。这些包括对象的所有内置方法,例如String的indexOf方法或Object的toString方法。但是,该循环将迭代所有用户定义的属性(包括任何覆盖内置属性的属性)。“为什么文档说”包括任何覆盖内置属性的属性“,如果在我的示例中.toString()没有被覆盖呢? - hekevintran

3

for..in循环遍历用户定义的属性。如果你将代码更改为:

Object.prototype.foo = function() { return 'abc'; };

那么

console.log(a);

将输出:

["a", "b", "c", "foo", "d"]

正如Chetan Sastry所指出的那样,toString与其他方法不同,因为它是一个内置的本地属性。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接