使用数组而不要使用字典来存储有序集合 1、for...in
循环除了枚举出对象“自身”的属性外,还会枚举出继承过来的属性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 function Animal ( ) { this .type = 'animal' ; } Animal.prototype.eat = function ( ) { console .log('eat ing...' ); }; var dog = new Animal();dog.age = 1 ; for (var attr in dog) { console .log(attr); }
for...in
循环的顺序不固定,如果需要依赖一个数据结构中的条目顺序,请使用数组
2、使用hasOwnProperty
方法可以排除继承过来的属性
1 2 3 4 5 6 7 8 9 for (var attr in dog) { if (dog.hasOwnProperty(attr)) { console .log(attr); } }
3、使用Object.defineProperty
方法可以定义一个对象的属性并指定该属性的元数据。
可以设置其枚举属性为false
使其在for...in
循环中不可见
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 function Animal ( ) { this .type = 'animal' ; } Object .defineProperty(Animal.prototype, 'eat' , { value: function ( ) { console .log('eat ing...' ); }, writable: true , enumerable: false , configurable: true }); var dog = new Animal();dog.age = 1 ; for (var attr in dog) { console .log(attr); }
避免在枚举期间修改对象 1、如果被枚举的对象在枚举期间添加了新的属性,那么在枚举期间并不能保证新添加的属性能够被访问。
2、当迭代一个对象时,如果该对象的内容可能在循环期间被改变,应该使用while循环或经典的for循环来代替for...in
循环
数组迭代要优先使用for循环而不是for…in循环 使用for...in
循环,对象的key始终是字符串
1 2 3 4 5 6 var scores = [1 ,2 ,3 ,4 ,5 ];var total = 0 ;for (var score in scores) { total += score; } console .log(total);
迭代方法优于循环 1、通过现有的数组建立一个新的数组。可以使用Array.prototype.map
方法
1 2 3 var trimmedArr = oldArr.map(function (s ) { return s.trim(); });
2、计算一个新的数组,该数组只包含现有数组的一些元素。可以使用Array.prototype.filter
。如果元素应该存在于新数组则返回真值,如果元素应该被剔除则返回假值。
1 2 3 4 5 6 7 var oldArr = [1 , 10 , 100 , 1000 , 10000 ];var filteredArr = oldArr.filter(function (item ) { return item >= 100 && item <= 10000 ; }); console .log(filteredArr);
3、循环只有一点优于迭代函数,那就是循环有控制流操作,如break
和continue
。举例来说,使用forEach
方法来实现takeWhile
函数将是一个尴尬的尝试。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 function takeWhile (a, pred ) { var result = []; for (var i = 0 , n = a.length; i < n; i++) { if (!pred(a[i], i)) { break ; } result[i] = a[i]; } return result; } var prefix = takeWhile([1 , 2 , 10 , 3 , 30 ], function (n ) { return n < 10 ; }); console .log(prefix);
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 function takeWhile (a, pred ) { var result = []; a.forEach(function (x, i ) { if (!pred(x)) { return ; } result[i] = x; }); return result; } var prefix = takeWhile([1 , 2 , 10 , 3 , 30 ], function (n ) { return n < 10 ; }); console .log(prefix);
return只是跳过了那一次循环,并没有终止掉循环。要想在forEach
中终止循环,可以使用一个内部异常来提前终止该循环
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 function takeWhile (a, pred ) { var result = []; var earlyExit = {}; try { a.forEach(function (x, i ) { if (!pred(x)) { throw earlyExit; } result[i] = x; }); } catch (e) { if (e !== earlyExit) { throw e; } } return result; } var prefix = takeWhile([1 , 2 , 10 , 3 , 30 ], function (n ) { return n < 10 ; }); console .log(prefix);
4、ES5的数组方法some
和every
可以用于提前终止循环
some
方法返回一个布尔值表示其回调对数组的任何一个元素 是否返回一个真值
every
方法返回一个布尔值表示其回调是否对所有元素 返回了一个真值
1 2 3 4 5 [1 , 10 , 100 ].some(function (x ) { return x > 5 ; }); [1 , 10 , 100 ].some(function (x ) { return x < 0 ; }); [1 , 2 , 3 , 4 , 5 ].every(function (x ) { return x > 0 ; }); [1 , 2 , 3 , 4 , 5 ].every(function (x ) { return x < 3 ; });
这两个方法都是短路循环。如果对some方法的回调一旦产生了一个真值,则some方法会直接返回,不会执行其余的元素。类似的,every方法的回调一旦产生了假值,则会立即返回
可以使用every
实现takeWhile
函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 function takeWhile (a, pred ) { var result = []; a.every(function (x, i ) { if (!pred(x)) { return false ; } result[i] = x; return true ; }); return result; } var prefix = takeWhile([1 , 2 , 10 , 3 , 30 ], function (n ) { return n < 10 ; }); console .log(prefix);
在类数组对象上复用通用的数组方法 1、DOM的NodeList类是另一个类数组对象的实例
2、数组对象的基本契约总共有两个简单的规则,满足后能使一个对象“看起来像数组”
具有一个范围在0到2^32-1的整型length属性
length属性大于该对象的最大索引。索引是一个范围在0到2^32-2的整数,它的字符串表示的是该对象的一个key
1 2 3 4 5 6 7 8 9 10 11 12 var arrayLike = { 0 : 'a' , 1 : 'b' , 2 : 'c' , length: 3 }; var result = Array .prototype.map.call(arrayLike, function (s ) { return s.toUpperCase(); }); console .log(result);
3、字符串也表现为不可变的数组,因为它们是可索引的,并且其长度也可以通过length属性获取。因此,Array.prototype中的方法操作字符串时并不会修改原始数组。
1 2 3 4 5 var result = Array .prototype.map.call('abc' , function (s ) { return s.toUpperCase(); }); console .log(result);
数组字面量优于数组构造函数 1、['hello']
和new Array("hello")
的行为相同,但[17]
和new Array[17]
的行为完全不同
2、如果使用单个数字参数来调用Array构造函数,它试图创建一个没有元素的数组,但其长度属性为给定的参数