浏览器中 for in 反射 对象成员 的差异
我们知道 众浏览器的js引擎 在 for in 反射 某对象成员时 是一次性获该对象的 比如
var obj={a:1};
for (var o in obj){
obj={a:1,b:2};
}
整个for 循环 只会执行一次 及时我们再循环内部改变了obj 的引用 但是 反射对象始终是 in后面那个obj的原始引用 .
也可以称作 for in 缓存了被反射对象.
但是我们看看另外一种情况
var obj={a:1};
var i=0;
for (var o in obj){
obj.b=2;
i++;
}
alert(i);
这里 浏览器出现了不一致性. 非ie浏览器 打印 1 而 ie 则打印2…
再说顺序问题 :
IE8-, firefox4-, safari5-, opera9.6- 都是按照加入顺序反射迭代的.
ie9+,opera10+,chrome3+ 初步观察为一种与ascii有关的排序.但并不完全按照ascii排序,即如果key的首字符以number开头,则该key按照ascii排序其他字符则按加入顺序排序,但其他字符的整体位置在ascii排序key的后面
chrome 2-则与chrome3+不同.其首字符非number开头的key整体位置在ascii排序key的前面.
测试代码:
var obj = {
'1' : 1,
'_' : 1,
'0' : 1,
'c' : 1,
'a' : 1,
'4' : 1,
'' : 1,
'b' : 1,
'3' : 1,
'2' : 1
},
a = [];
for (var o in obj){
a.push(o);
}
alert(a);
IE8-, firefox4-, safari5-, opera9.6-
顺序: 1,_,0,c,a,4,,b,3,2
chrome 3+
顺序: 0,1,2,3,4,_,c,a,,b
chrome 2-
顺序: _,c,a,,b,0,1,2,3,4
关于对arguments的枚举:
对Chromium V8(Chrome4+以后版本)引擎浏览器 及 Opera 所使用过的4种JavaScript引擎,以及IE9+,Firefox4+未遵守ECMA262 Edition3 ,arguments[index]的不可枚举性规范.而遵守了ECMA262 Edition5 允许枚举. 但Opera的早期版本根本没有考虑过ES5,所以究其根本是,其早期完全没有遵守现行标准. Saraf5-始终不可枚举arguments.
参考代码:
void function () {
for (var o in arguments){
alert(o);
}
}(1,2,3);
然后两个和语法相关的:
Number.prototype.test = 1; for(s in NaN)alert(s);
被反射的如果是一个原始值类型,则此处会创建一个该值的类型对应的包装对象,且s,作为左值表达式,是可以未声明直接就引用的.
IE系的另一个bug(IE8-) (也就是说他们居然为任何对象的toString和valueOf属性添加了[[DontEnum]]特性,参考ES5的[[Enumable]]=false)
var a = { toString : function () {},valueOf : 456 };
for (var i in a) {
alert(i);
}
IE6-8是不会有任何打印的
最后 一个小技巧 :
var a = []; for (a[a.length] in obj);
这样就得到了一个 obj 可枚举的 key的元素构成的数组了. ECMA262 v3 12.6.4章节明确指出. in运算符左边可以是一个表达式.而不必须是一个 变量标识符.
浙公网安备 33010602011771号