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


posted @ 2010-05-08 13:51  Franky  阅读(2120)  评论(4编辑  收藏  举报