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

关于for-in循环的一些使用上应该注意的细节

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

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

作者: happyWang

Hello, the beautiful world

发表评论