为什么javascript对象的内置属性在使用for-in控制块时没有迭代,而用户定义的属性是?
例如:
var y = 'car';
for (var j in y)
{
console.log(j);
}
将打印:
0
1
2
尽管String.prototype具有length,replace,substring等属性
但是,如果扩展原型,任何新属性都会迭代:
String.prototype.foo = 7;
var y = 'car';
for (var j in y)
{
console.log(j);
}
将打印:
0
1
2
foo
答案 0 :(得分:3)
基本上,内置属性在内部标记为“不可枚举”。这自然意味着它们没有被列举。
编辑:正如Andy所指出的那样,可以使用enumerable : false
在当前版本的JavaScript中设置defineProperty
。但是,这似乎根本不支持Opera; IE 8仅在DOM对象上支持它,而Safari仅在非 -DOM对象(defineProperty on MDN上支持它(查看文件底部以获得浏览器支持))。
所有这些跨浏览器的乐趣意味着如果您需要一致的浏览器支持,您可能不应该依赖此行为。
以下是如何定义不可枚举的属性:
Object.defineProperty(String.prototype, "foo", {value : 7, enumerable : false});
您实际上不需要包含enumerable : false
- 在调用false
时默认为defineProperty
。
答案 1 :(得分:3)
有propertyIsEnumerable方法,它返回一个布尔值,指示是否设置了内部ECMAScript DontEnum attribute(还要注意实现之间可怕的分歧)。如上所述,您无法设置DontEnum
,只能通过propertyIsEnumerable
进行查询。
答案 2 :(得分:2)
在
var y = 'car';
for (var j in y) {
console.log(j);
}
您正在遍历String实例的属性,该实例被视为一个字符数组。在这种情况下,数组有3个元素,因此它的'属性'是0,1,2。如果您console.logged
y[j]
,您应该看到'c','a','r'
。
现在,如果你想查看原型属性/方法,你应该查询y的constructor
原型(String
)的原型:
for (var j in y.constructor.prototype)
{
console.log(j);
}
在
String.prototype.foo = 7;
var y = 'car';
for (var j in y) {
console.log(j);
}
您向foo
添加了一个属性String.prototype
。向构造函数(String)原型添加属性使其可用于所有实例。字符串文字y
是String
的一个实例,因此当您枚举其属性时,您会在foo
中看到y
。
另请参阅:this SO question
答案 3 :(得分:1)
要扩展所有人的回答,您可以使用Object.defineProperty
var o = {},
def = Object.defineProperty;
def(o, "myProperty", {
"value": 42,
"enumerable": false,
"writeable": true,
"configurable": true
});
请注意,这些属性默认为false,因此您不能包含"enumerable"
将其设置为false。