浏览器中 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运算符左边可以是一个表达式.而不必须是一个 变量标识符.