Javascript for-in和内置属性

时间:2011-05-09 18:21:39

标签: javascript

为什么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

4 个答案:

答案 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)原型添加属性使其可用于所有实例。字符串文字yString的一个实例,因此当您枚举其属性时,您会在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。