Javascript for-in and built-in properties



为什么在使用for-in控制块时,javascript对象上的内置属性没有迭代,而用户定义的属性是?

例如:

var y = 'car';
for (var j in y)
{
    console.log(j);
}

将打印:

0
1
2

即使 String.prototype 具有长度、替换、子字符串等属性。

但是,如果扩展原型,则会迭代任何新属性:

String.prototype.foo = 7;
var y = 'car';
for (var j in y)
{
    console.log(j);
}

将打印:

0
1
2
foo

基本上,内置属性在内部标记为"不可枚举"。这意味着,自然不会枚举它们。

编辑:正如Andy善意指出的那样,您可以使用defineProperty在当前版本的JavaScript中设置enumerable : false。但是,这似乎根本不支持 Opera ;IE 8 只在 DOM 对象上支持它,而 Safari 只在 DOM 对象上支持它(在 MDN 上定义属性(查看文件底部以获得浏览器支持))。

所有这些跨浏览器的乐趣意味着,如果您需要一致的浏览器支持,您可能不应该依赖此行为。

下面介绍如何定义不可枚举的属性:

Object.defineProperty(String.prototype, "foo", {value : 7, enumerable : false});

您实际上不需要包含enumerable : false - 默认情况下,在调用defineProperty时会false它。

有一个 propertyIsEnumerable 方法,它返回一个布尔值,指示是否设置了内部 ECMAScript DontEnum 属性(还要注意实现之间的可怕分歧)。如上所述,您不能设置DontEnum,而只能通过propertyIsEnumerable查询。

in

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中,当枚举它的属性时。

另请参阅:这个SO问题

要扩展其他人的答案,您可以使用Object.defineProperty将自己的属性标记为不可枚举

var o = {},
    def = Object.defineProperty;
def(o, "myProperty", {
   "value": 42,
   "enumerable": false,
   "writeable": true,
   "configurable": true
});

请注意,这些属性默认为 false,因此您可以不包含 "enumerable" 以将其设置为 false。

相关内容

最新更新