Javascript for in-loop和delete操作符
我注意到,在枚举对象的属性时,似乎在循环开始时获取了当前属性的快照,然后对快照进行迭代。我之所以这样认为,是因为以下内容不会产生无休止的循环:Javascript for in-loop和delete操作符,javascript,Javascript,我注意到,在枚举对象的属性时,似乎在循环开始时获取了当前属性的快照,然后对快照进行迭代。我之所以这样认为,是因为以下内容不会产生无休止的循环: var obj = {a:0,b:0}, i=0; for (var k in obj) { obj[i++] = 0; } alert(i) // 2 演示 上面的代码演示了我正在添加新属性,但不会枚举新属性 然而,delete操作符似乎违背了我的快照理论。这是相同的代码,但是在枚举属性之前删除它 var obj = {a:0,b:0}, i
var obj = {a:0,b:0}, i=0;
for (var k in obj) {
obj[i++] = 0;
}
alert(i) // 2
演示
上面的代码演示了我正在添加新属性,但不会枚举新属性
然而,delete操作符似乎违背了我的快照理论。这是相同的代码,但是在枚举属性之前删除它
var obj = {a:0,b:0}, i=0;
for (var k in obj) {
i++;
delete obj.b;
}
alert(i) // 1
演示
上面的代码演示了循环体只执行一次。如果快照理论是真的,它会执行两次
这是怎么回事?javascript是否有它使用的某种类型的隐藏迭代器,并且delete操作符不知何故知道它
--我意识到我假设了一些关于迭代顺序的东西——特别是迭代是基于属性插入时间发生的。我相信所有浏览器都使用这样的实现代码> 第一次迭代:
此外,javascript
for in
循环在对象上迭代时不能保证按顺序执行。因此,删除obj.b代码>产生不可预测的结果 有趣的问题。答案在于(我的重点):
未指定枚举属性的机制和顺序(第一个算法中的步骤6.a,第二个算法中的步骤7.a)。枚举期间可能会删除正在枚举的对象的属性如果删除枚举期间尚未访问的属性,则不会访问该属性。如果在枚举期间向正在枚举的对象添加新属性,则不保证在活动枚举中访问新添加的属性。在任何枚举中,属性名称的访问次数不得超过一次
因此,它明确规定,删除的属性不能再被遍历。但是,添加新属性的行为取决于实现,很可能是因为没有定义如何在内部存储属性
例如,在Chrome中,数字属性似乎存储在字母属性之前:
> Object.keys({a:0, 0:1});
["0", "a"]
但是,即使添加字母键:
var obj = {a:0,b:0};
for (var k in obj) {
obj['c'] = 0;
console.log(k);
}
c
似乎没有被遍历,输出是ab
Firefox显示了相同的行为,尽管按键是按插入顺序存储的:
> Object.keys({a:0, 0:1});
["a", "0"]
与其说<代码>for…in
循环不能保证按顺序完成,不如说它们不能保证按顺序完成@kojiro-不确定这些不是反向等价的,但是如果这有助于阅读本文的其他人,那么感谢您的澄清。太好了!尤其值得注意的是,在某些实现中,循环可能是无限的。是的,这绝对是值得注意的。