使用数组而不要使用字典来存储有序集合 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构造函数,它试图创建一个没有元素的数组,但其长度属性为给定的参数