编写可维护的JavaScript-语句和表达式

作者 happyWang 日期 2014-10-14 Views
编写可维护的JavaScript-语句和表达式

matainable javascript : For-In 循环

本系列的文章都是在阅读《编写可维护的JavaScript》——Nicbolas C. Zakas 的基础上做的一些个人总结

for-in 循环

### 遍历对象

对对象使用for in循环的时候,一般情况下,都应该使用hasOwnProperty()方法来进行过滤:

var prop,
    obj = {
        a: "aaa",
        b: "bbb"
    };

for (prop in obj) {
    if (obj.hasOwnProperty(prop) {
        console.log("Property name is " + prop);
        console.log("Property value is " + obj\[prop\]);
    }
}

如果的确需要查询原型链,这个时候应当补充注释

var prop,
    obj = {
        a: "aaa",
        b: "bbb"
    };

for (prop in obj) { // 包含对原型链的遍历
    console.log("Property name is " + prop);
    console.log("Property value is " + obj\[prop\]);
}

### 不要使用for in 来遍历数组

// 不好的用法
var values = \[ 1, 2, 3, 4, 5, 6, 7\],
    i;
    
for (i in values) {
    console.log(values\[i\]);
}

不使用for in来遍历数组,是因为这样会造成一些潜在的错误,同时会有性能上面的影响。 潜在的错误:

var arr = \[ 'a', 'b', 'c'\],
    i;

arr.test = 'ddd';

for ( i in arr ){
    console.log(i,arr\[i\]);
}

/** 输出内容
* 0 a 
* 1 b 
* 2 c 
* test tset 
*/

可见for in循环会把用户附加在数组上的一些自定义属性输出,这很可能会导致一些潜在的错误,因为这段代码的作者的目的是需要的数组成员的数据 性能问题(摘自JavaScript秘密花园):

由于 for in 循环会枚举原型链上的所有属性,唯一过滤这些属性的方式是使用 hasOwnProperty 函数, 因此会比普通的 for 循环慢上好多倍。

做个测试:

var arr = \[\],
    i,
    a,
    max = 100000,
    timeStart,
    timeEnd;

// 生成一个长度100000的数组
for (i = 0; i < max; i++) {
    arr\[i\] = i;
}

/**
* for 循环
*/
timeStart = new Date().valueOf();
for (i = 0; i < max; i++) {
    // 无意义的一些操作
    a = arr\[i\];
}
timeEnd = new Date().valueOf();

console.log(timeEnd - timeStart);

/**
* for in 循环
*/
timeStart = new Date().valueOf();
for (i in arr) {
    // 无意义的一些操作
    a = arr\[i\];
}
timeEnd = new Date().valueOf();

console.log(timeEnd - timeStart);

在数组长度比较小的时候,两者差距不大 甚至有的时候for in还会快一点 但是随着数组长度越来越大,两者的差距也就越来越明显 下面是一串本机的测试数据(Mac Chrome 37.0.2062.122)

数组长度 for for-in
10 0 0
1000 0 1
10000 1 6
100000 2 46
1000000 24 331
10000000 207 4362

虽然在实际项目中,数组的长度不会那么长,但是能提高一点效率总是好的