天天看点

for in arguments/array

        在项目前端JS开发中,无意中有段代码去遍历arguments(入参对象), arguments为一个参数对象,即我们可以通过arguments[0],arguments[1]去访问对应的第N个参数(刚开始我认为它是一个数组)。在代码中,我是通过for in 去遍历arguments对象的,在chrome,firefox,ie9+都是支持的。然后在ie7等低版本IE7则就哑了。然而在下图代码中,在IE7中遍历数组却是正常的。

var arr = ["12", "test"];  
for (var i in arr) {  alert(i); } //依次打印出0,1(即数组的下标)      

     这个时候我却茫然了,这个是怎么回事呢?难道是arguments对象比较特殊?通过$.type(arguments)查看其返回结果得知,arguments非数组。再到见多上查询:arguments并非真正的数组,它是一个Arguments对象。正好验证了我的想法。arguments 遍历的方法也跟数组遍历的方式一样,即for var遍历。

     另外,数组遍历最好用for var而非for in,否则会产生非预期的结果。那是因为for in 语句对数组对象进行遍历潜在的bug在于:如果原生Array类被其他的js脚本库进行了原型扩展(比如多加一个toJSON方法即Array.prototype.hello=xxxx),那么用for in遍历扩展后的Array对象的逻辑将与遍历原生Array对象的逻辑发生差异。

     按上图代码,如果Array是原生js类,那么结果就是我们预期的结果。但是,如果Array类被扩展了,多了一个hello方法,那么上面的语句将执行三次alert,//依次打印出0,1, hello(即数组的下标)。

     如果你设计的代码的逻辑以原生Array类为基准,在某一天你的同事在页面里面引用了一个第三方的JS库,这个库又恰好扩展了Array类,结果将难以想象,很有可能原来的代码逻辑将不再成立。 

        关于这种扩展原生JS类的库,很有名的一个就是prototype.js,它给Array类扩展了很多方法诸如toJSON,each等等。我现在明白为啥jquery的创始人曾经对prototype火大了(不少人因为特殊原因在一个页面里用jquery同时又用prototype,会有很多意料之外的冲突问题,仅仅一个noConflict是无法解决的)。

        所以,在数组遍历中用for var 代替for in。

继续阅读