要取得 
  Array 
  的长度,直接访问 
  length 
  属性: 
 
 
  
   
   var 
   arr = [ 
   1 
   , 
   2 
   , 
   3.14 
   , 
   'Hello' 
   , null, true]; 
  
 
   
   arr.length; 
   // 6 
  
 
   
  
  请注意 
  ,直接给 
  Array 
  的 
  length 
  赋一个新的值会导致 
  Array 
  大小的变化: 
 
 
  
   
   var 
   arr = [ 
   1 
   , 
   2 
   , 
   3 
   ]; 
  
 
   
   arr.length; 
   // 3 
  
 
   
   arr.length = 
   6 
   ; 
  
 
   
   arr; 
   // arr变为[1, 2, 3, undefined, undefined, undefined] 
  
 
   
   arr.length = 
   2 
   ; 
  
 
   
   arr; 
   // arr变为[1, 2] 
  
 
   
  
  Array 
  可以通过索引把对应的元素修改为新的值,因此,对 
  Array 
  的索引进行赋值会直接修改这个 
  Array 
  : 
 
 
  
   
   var 
   arr = [ 
   'A' 
   , 
   'B' 
   , 
   'C' 
   ]; 
  
 
   
   arr[ 
   1 
   ] = 
   99 
   ; 
  
 
   
   arr; 
   // arr现在变为['A', 99, 'C'] 
  
 
   
  
  请注意 
  ,如果通过索引赋值时,索引超过了范围,同样会引起 
  Array 
  大小的变化: 
 
 
  
   
   var 
   arr = [ 
   1 
   , 
   2 
   , 
   3 
   ]; 
  
 
   
   arr[ 
   5 
   ] = 
   'x' 
   ; 
  
 
   
   arr; 
   // arr变为[1, 2, 3, undefined, undefined, 'x'] 
  
 
   
  
  大多数其他编程语言不允许直接改变数组的大小,越界访问索引会报错。然而,JavaScript的 
  Array 
  却不会有任何错误。在编写代码时,不建议直接修改 
  Array 
  的大小,访问索引时要确保索引不会越界。 
 
 
  indexOf
 
  
  与String类似, 
  Array 
  也可以通过 
  indexOf() 
  来搜索一个指定的元素的位置: 
 
 
  
   
   var 
   arr = [ 
   10 
   , 
   20 
   , 
   '30' 
   , 
   'xyz' 
   ]; 
  
 
   
   arr.indexOf( 
   10 
   ); 
   // 元素10的索引为0 
  
 
   
   arr.indexOf( 
   20 
   ); 
   // 元素20的索引为1 
  
 
   
   arr.indexOf( 
   30 
   ); 
   // 元素30没有找到,返回-1 
  
 
   
   arr.indexOf( 
   '30' 
   ); 
   // 元素'30'的索引为2 
  
 
   
  
  注意了,数字 
  30 
  和字符串 
  '30' 
  是不同的元素。 
 
 
  slice
 
  
  slice() 
  就是对应String的 
  substring() 
  版本,它截取 
  Array 
  的部分元素,然后返回一个新的 
  Array 
  : 
 
 
  
   
   var 
   arr = [ 
   'A' 
   , 
   'B' 
   , 
   'C' 
   , 
   'D' 
   , 
   'E' 
   , 
   'F' 
   , 
   'G' 
   ]; 
  
 
   
   arr.slice( 
   0 
   , 
   3 
   ); 
   // 从索引0开始,到索引3结束,但不包括索引3: ['A', 'B', 'C'] 
  
 
   
   arr.slice( 
   3 
   ); 
   // 从索引3开始到结束: ['D', 'E', 'F', 'G'] 
  
 
   
  
  注意到 
  slice() 
  的起止参数包括开始索引,不包括结束索引。 
 
 
  
  如果不给 
  slice() 
  传递任何参数,它就会从头到尾截取所有元素。利用这一点,我们可以很容易地复制一个 
  Array 
  : 
 
 
  
   
   var 
   arr = [ 
   'A' 
   , 
   'B' 
   , 
   'C' 
   , 
   'D' 
   , 
   'E' 
   , 
   'F' 
   , 
   'G' 
   ]; 
  
 
   
   var 
   aCopy = arr.slice(); 
  
 
   
   aCopy; 
   // ['A', 'B', 'C', 'D', 'E', 'F', 'G'] 
  
 
   
   aCopy === arr; 
   // false 
  
 
   
  push和pop
 
  
  push() 
  向 
  Array 
  的末尾添加若干元素, 
  pop() 
  则把 
  Array 
  的最后一个元素删除掉: 
 
 
  
   
   var 
   arr = [ 
   1 
   , 
   2 
   ]; 
  
 
   
   arr.push( 
   'A' 
   , 
   'B' 
   ); 
   // 返回Array新的长度: 4 
  
 
   
   arr; 
   // [1, 2, 'A', 'B'] 
  
 
   
   arr.pop(); 
   // pop()返回'B' 
  
 
   
   arr; 
   // [1, 2, 'A'] 
  
 
   
   arr.pop(); arr.pop(); arr.pop(); 
   // 连续pop 3次 
  
 
   
   arr; 
   // [] 
  
 
   
   arr.pop(); 
   // 空数组继续pop不会报错,而是返回undefined 
  
 
   
   arr; 
   // [] 
  
 
   
  unshift和shift
 
  
  如果要往 
  Array 
  的头部添加若干元素,使用 
  unshift() 
  方法, 
  shift() 
  方法则把 
  Array 
  的第一个元素删掉: 
 
 
  
   
   var 
   arr = [ 
   1 
   , 
   2 
   ]; 
  
 
   
   arr.unshift( 
   'A' 
   , 
   'B' 
   ); 
   // 返回Array新的长度: 4 
  
 
   
   arr; 
   // ['A', 'B', 1, 2] 
  
 
   
   arr.shift(); 
   // 'A' 
  
 
   
   arr; 
   // ['B', 1, 2] 
  
 
   
   arr.shift(); arr.shift(); arr.shift(); 
   // 连续shift 3次 
  
 
   
   arr; 
   // [] 
  
 
   
   arr.shift(); 
   // 空数组继续shift不会报错,而是返回undefined 
  
 
   
   arr; 
   // [] 
  
 
   
  sort
 
  
  sort() 
  可以对当前 
  Array 
  进行排序,它会直接修改当前 
  Array 
  的元素位置,直接调用时,按照默认顺序排序: 
 
 
  
   
   var 
   arr = [ 
   'B' 
   , 
   'C' 
   , 
   'A' 
   ]; 
  
 
   
   arr.sort(); 
  
 
   
   arr; 
   // ['A', 'B', 'C'] 
  
 
   
  
  能否按照我们自己指定的顺序排序呢?完全可以,我们将在后面的函数中讲到。 
 
 
  reverse
 
  
  reverse() 
  把整个 
  Array 
  的元素给掉个个,也就是反转: 
 
 
  
   
   var 
   arr = [ 
   'one' 
   , 
   'two' 
   , 
   'three' 
   ]; 
  
 
   
   arr.reverse(); 
  
 
   
   arr; 
   // ['three', 'two', 'one'] 
  
 
   
  splice
 
  
  splice() 
  方法是修改 
  Array 
  的“万能方法”,它可以从指定的索引开始删除若干元素,然后再从该位置添加若干元素: 
 
 
  
   
   var 
   arr = [ 
   'Microsoft' 
   , 
   'Apple' 
   , 
   'Yahoo' 
   , 
   'AOL' 
   , 
   'Excite' 
   , 
   'Oracle' 
   ]; 
  
 
   
   // 从索引2开始删除3个元素,然后再添加两个元素: 
  
 
   
   arr.splice( 
   2 
   , 
   3 
   , 
   'Google' 
   , 
   'Facebook' 
   ); 
   // 返回删除的元素 ['Yahoo', 'AOL', 'Excite'] 
  
 
   
   arr; 
   // ['Microsoft', 'Apple', 'Google', 'Facebook', 'Oracle'] 
  
 
   
   // 只删除,不添加: 
  
 
   
   arr.splice( 
   2 
   , 
   2 
   ); 
   // ['Google', 'Facebook'] 
  
 
   
   arr; 
   // ['Microsoft', 'Apple', 'Oracle'] 
  
 
   
   // 只添加,不删除: 
  
 
   
   arr.splice( 
   2 
   , 
   0 
   , 
   'Google' 
   , 
   'Facebook' 
   ); 
   // 返回[],因为没有删除任何元素 
  
 
   
   arr; 
   // ['Microsoft', 'Apple', 'Google', 'Facebook', 'Oracle'] 
  
 
   
  concat
 
  
  concat() 
  方法把当前的 
  Array 
  和另一个 
  Array 
  连接起来,并返回一个新的 
  Array 
  : 
 
 
  
   
   var 
   arr = [ 
   'A' 
   , 
   'B' 
   , 
   'C' 
   ]; 
  
 
   
   var 
   added = arr.concat([ 
   1 
   , 
   2 
   , 
   3 
   ]); 
  
 
   
   added; 
   // ['A', 'B', 'C', 1, 2, 3] 
  
 
   
   arr; 
   // ['A', 'B', 'C'] 
  
 
   
  
  请注意 
  , 
  concat() 
  方法并没有修改当前 
  Array 
  ,而是返回了一个新的 
  Array 
  。 
 
 
  
  实际上, 
  concat() 
  方法可以接收任意个元素和 
  Array 
  ,并且自动把 
  Array 
  拆开,然后全部添加到新的 
  Array 
  里: 
 
 
  
   
   var 
   arr = [ 
   'A' 
   , 
   'B' 
   , 
   'C' 
   ]; 
  
 
   
   arr.concat( 
   1 
   , 
   2 
   , [ 
   3 
   , 
   4 
   ]); 
   // ['A', 'B', 'C', 1, 2, 3, 4] 
  
 
   
  join
 
  
  join() 
  方法是一个非常实用的方法,它把当前 
  Array 
  的每个元素都用指定的字符串连接起来,然后返回连接后的字符串: 
 
 
  
   
   var 
   arr = [ 
   'A' 
   , 
   'B' 
   , 
   'C' 
   , 
   1 
   , 
   2 
   , 
   3 
   ]; 
  
 
   
   arr.join( 
   '-' 
   ); 
   // 'A-B-C-1-2-3' 
  
 
   
  
  如果 
  Array 
  的元素不是字符串,将自动转换为字符串后再连接。 
 
 
  
  
 
 
 
  
 
  
   
   const a1 
   = 
   [ 
   1 
   , 
   2 
   ] 
   ; 
  
 
   
   // 写法一 
  
 
   
   const a2 
   = 
   [ 
   . 
   . 
   . 
   a1 
   ] 
   ; 
  
 
   
   // 写法二 
  
 
   
   const 
   [ 
   . 
   . 
   . 
   a2 
   ] 
   = 
   a1 
   ; 
  
 
   
    (2)合并数组 
  
 
   
   扩展运算符提供了数组合并的新写法。 
  
 
   
    
    const arr1 
    = 
    [ 
    'a' 
    , 
    'b' 
    ] 
    ; 
   
 
    
    const arr2 
    = 
    [ 
    'c' 
    ] 
    ; 
   
 
    
    const arr3 
    = 
    [ 
    'd' 
    , 
    'e' 
    ] 
    ; 
   
 
    
    
 
   
 
    
    // ES5 的合并数组 
   
 
    
    arr1 
    . 
    concat 
    ( 
    arr2 
    , 
    arr3 
    ) 
    ; 
   
 
    
    // [ 'a', 'b', 'c', 'd', 'e' ] 
   
 
    
    // ES6 的合并数组 
   
 
    
    [ 
    . 
    . 
    . 
    arr1 
    , 
    . 
    . 
    . 
    arr2 
    , 
    . 
    . 
    . 
    arr3 
    ] 
   
 
    
    // [ 'a', 'b', 'c', 'd', 'e' ] 
   
 
    
   
   不过,这两种方法都是浅拷贝,使用的时候需要注意。 
  
 
   
    
    const a1 
    = 
    [ 
    { 
    foo 
    : 
    1 
    } 
    ] 
    ; 
   
 
    
    const a2 
    = 
    [ 
    { 
    bar 
    : 
    2 
    } 
    ] 
    ; 
   
 
    
    
 
   
 
    
    const a3 
    = 
    a1 
    . 
    concat 
    ( 
    a2 
    ) 
    ; 
   
 
    
    const a4 
    = 
    [ 
    . 
    . 
    . 
    a1 
    , 
    . 
    . 
    . 
    a2 
    ] 
    ; 
   
 
    
    
 
   
 
    
    a3 
    [ 
    0 
    ] 
    === 
    a1 
    [ 
    0 
    ] 
    // true 
   
 
    
    a4 
    [ 
    0 
    ] 
    === 
    a1 
    [ 
    0 
    ] 
    // true 
   
 
    
   
   上面代码中, 
   a3 
   和 
   a4 
   是用两种不同方法合并而成的新数组,但是它们的成员都是对原数组成员的引用,这就是浅拷贝。如果修改了引用指向的值,会同步反映到新数组。 
  
 
   
   3)与解构赋值结合 
  
 
   
   扩展运算符可以与解构赋值结合起来,用于生成数组。 
  
 
   
    
    // ES5 
   
 
    
    a 
    = 
    list 
    [ 
    0 
    ] 
    , 
    rest 
    = 
    list 
    . 
    slice 
    ( 
    1 
    ) 
   
 
    
    // ES6 
   
 
    
    [ 
    a 
    , 
    . 
    . 
    . 
    rest 
    ] 
    = 
    list 
   
 
    
   
   下面是另外一些例子。 
  
 
   
    
    const 
    [ 
    first 
    , 
    . 
    . 
    . 
    rest 
    ] 
    = 
    [ 
    1 
    , 
    2 
    , 
    3 
    , 
    4 
    , 
    5 
    ] 
    ; 
   
 
    
    first 
    // 1 
   
 
    
    rest 
    // [2, 3, 4, 5] 
   
 
    
    const 
    [ 
    first 
    , 
    . 
    . 
    . 
    rest 
    ] 
    = 
    [ 
    ] 
    ; 
   
 
    
    first 
    // undefined 
   
 
    
    rest 
    // [] 
   
 
    
    const 
    [ 
    first 
    , 
    . 
    . 
    . 
    rest 
    ] 
    = 
    [ 
    "foo" 
    ] 
    ; 
   
 
    
    first 
    // "foo" 
   
 
    
    rest  
    // [] 
   
 
    
   
   如果将扩展运算符用于数组赋值,只能放在参数的最后一位,否则会报错。 
  
 
   
    
    const 
    [ 
    . 
    . 
    . 
    butLast 
    , 
    last 
    ] 
    = 
    [ 
    1 
    , 
    2 
    , 
    3 
    , 
    4 
    , 
    5 
    ] 
    ; 
   
 
    
    // 报错 
   
 
    
    const 
    [ 
    first 
    , 
    . 
    . 
    . 
    middle 
    , 
    last 
    ] 
    = 
    [ 
    1 
    , 
    2 
    , 
    3 
    , 
    4 
    , 
    5 
    ] 
    ; 
   
 
    
    // 报错 
   
 
    
   
   (4)字符串 
  
 
   
   扩展运算符还可以将字符串转为真正的数组。 
  
 
   
    
    [ 
    . 
    . 
    . 
    'hello' 
    ] 
   
 
    
    // [ "h", "e", "l", "l", "o" ] 
   
 
    
   
    
 
  
 
   Array.from()  §   ⇧
 
   
   Array.from 
   方法用于将两类对象转为真正的数组:类似数组的对象(array-like object)和可遍历(iterable)的对象(包括 ES6 新增的数据结构 Set 和 Map)。 
  
 
   
   下面是一个类似数组的对象, 
   Array.from 
   将它转为真正的数组。 
  
 
   
    
    let 
    arrayLike 
    = 
    { 
   
 
    
        
    '0' 
    : 
    'a' 
    , 
   
 
    
        
    '1' 
    : 
    'b' 
    , 
   
 
    
        
    '2' 
    : 
    'c' 
    , 
   
 
    
        length 
    : 
    3 
   
 
    
    } 
    ; 
   
 
    
    
 
   
 
    
    // ES5的写法 
   
 
    
    var 
    arr1 
    = 
    [ 
    ] 
    . 
    slice 
    . 
    call 
    ( 
    arrayLike 
    ) 
    ; 
    // ['a', 'b', 'c'] 
   
 
    
    // ES6的写法 
   
 
    
    let 
    arr2 
    = 
    Array 
    . 
    from 
    ( 
    arrayLike 
    ) 
    ; 
    // ['a', 'b', 'c'] 
   
 
    
   
  
  只要是部署了 Iterator 接口的数据结构, 
  Array.from 
  都能将其转为数组。 
 
 
  
   
   Array 
   . 
   from 
   ( 
   'hello' 
   ) 
  
 
   
   // ['h', 'e', 'l', 'l', 'o'] 
  
 
   
   let 
   namesSet 
   = 
   new 
   Set 
   ( 
   [ 
   'a' 
   , 
   'b' 
   ] 
   ) 
  
 
   
   Array 
   . 
   from 
   ( 
   namesSet 
   ) 
   // ['a', 'b'] 
  
 
   
  
  Array.from 
  还可以接受第二个参数,作用类似于数组的 
  map 
  方法,用来对每个元素进行处理,将处理后的值放入返回的数组。 
 
 
  
   
   Array 
   . 
   from 
   ( 
   arrayLike 
   , 
   x 
   = 
   > 
   x 
   * 
   x 
   ) 
   ; 
  
 
   
   // 等同于 
  
 
   
   Array 
   . 
   from 
   ( 
   arrayLike 
   ) 
   . 
   map 
   ( 
   x 
   = 
   > 
   x 
   * 
   x 
   ) 
   ; 
  
 
   
   
 
  
 
   
   Array 
   . 
   from 
   ( 
   [ 
   1 
   , 
   2 
   , 
   3 
   ] 
   , 
   ( 
   x 
   ) 
   = 
   > 
   x 
   * 
   x 
   ) 
  
 
   
   // [1, 4, 9] 
  
 
   
  
  Array.of()
 
  
  Array.of 
  方法用于将一组值,转换为数组。 
 
 
  
   
   Array 
   . 
   of 
   ( 
   3 
   , 
   11 
   , 
   8 
   ) 
   // [3,11,8] 
  
 
   
   Array 
   . 
   of 
   ( 
   3 
   ) 
   // [3] 
  
 
   
   Array 
   . 
   of 
   ( 
   3 
   ) 
   . 
   length 
   // 1 
  
 
   
  
  这个方法的主要目的,是弥补数组构造函数 
  Array() 
  的不足。因为参数个数的不同,会导致 
  Array() 
  的行为有差异。 
 
 
  
   
   Array 
   ( 
   ) 
   // [] 
  
 
   
   Array 
   ( 
   3 
   ) 
   // [, , ,] 
  
 
   
   Array 
   ( 
   3 
   , 
   11 
   , 
   8 
   ) 
   // [3, 11, 8] 
  
 
   
  
  上面代码中, 
  Array 
  方法没有参数、一个参数、三个参数时,返回结果都不一样。只有当参数个数不少于 2 个时, 
  Array() 
  才会返回由参数组成的新数组。参数个数只有一个时,实际上是指定数组的长度。 
 
 
  
  Array.of 
  基本上可以用来替代 
  Array() 
  或 
  new Array() 
  ,并且不存在由于参数不同而导致的重载。它的行为非常统一。 
 
 
  
   
   Array 
   . 
   of 
   ( 
   ) 
   // [] 
  
 
   
   Array 
   . 
   of 
   ( 
   undefined 
   ) 
   // [undefined] 
  
 
   
   Array 
   . 
   of 
   ( 
   1 
   ) 
   // [1] 
  
 
   
   Array 
   . 
   of 
   ( 
   1 
   , 
   2 
   ) 
   // [1, 2] 
  
 
   
  
  Array.of 
  总是返回参数值组成的数组。如果没有参数,就返回一个空数组。 
 
 
  
  Array.of 
  方法可以用下面的代码模拟实现。 
 
 
  
   
   function 
   ArrayOf 
   ( 
   ) 
   { 
  
 
   
     
   return 
   [ 
   ] 
   . 
   slice 
   . 
   call 
   ( 
   arguments 
   ) 
   ; 
  
 
   
   } 
  
 
   
  数组实例的 copyWithin()
 
  
  数组实例的 
  copyWithin() 
  方法,在当前数组内部,将指定位置的成员复制到其他位置(会覆盖原有成员),然后返回当前数组。也就是说,使用这个方法,会修改当前数组。 
 
 
  
  Array 
  . 
  prototype 
  . 
  copyWithin 
  ( 
  target 
  , 
  start 
  = 
  0 
  , 
  end 
  = 
  this 
  . 
  length 
  ) 
 
 
  
  它接受三个参数。 
 
 
  
  -  target(必需):从该位置开始替换数据。如果为负值,表示倒数。
  
  -  start(可选):从该位置开始读取数据,默认为 0。如果为负值,表示从末尾开始计算。
  
  -  end(可选):到该位置前停止读取数据,默认等于数组长度。如果为负值,表示从末尾开始计算。
  
 
 
  
  这三个参数都应该是数值,如果不是,会自动转为数值。 
 
 
  
   
   [ 
   1 
   , 
   2 
   , 
   3 
   , 
   4 
   , 
   5 
   ] 
   . 
   copyWithin 
   ( 
   0 
   , 
   3 
   ) 
  
 
   
   // [4, 5, 3, 4, 5] 
  
 
   
  
  上面代码表示将从 3 号位直到数组结束的成员(4 和 5),复制到从 0 号位开始的位置,结果覆盖了原来的 1 和 2。 
 
 
  
  下面是更多例子。 
 
 
  
   
   // 将3号位复制到0号位 
  
 
   
   [ 
   1 
   , 
   2 
   , 
   3 
   , 
   4 
   , 
   5 
   ] 
   . 
   copyWithin 
   ( 
   0 
   , 
   3 
   , 
   4 
   ) 
  
 
   
   // [4, 2, 3, 4, 5] 
  
 
   
   // -2相当于3号位,-1相当于4号位 
  
 
   
   [ 
   1 
   , 
   2 
   , 
   3 
   , 
   4 
   , 
   5 
   ] 
   . 
   copyWithin 
   ( 
   0 
   , 
   - 
   2 
   , 
   - 
   1 
   ) 
  
 
   
   // [4, 2, 3, 4, 5] 
  
 
   
   // 将3号位复制到0号位 
  
 
   
   [ 
   ] 
   . 
   copyWithin 
   . 
   call 
   ( 
   { 
   length 
   : 
   5 
   , 
   3 
   : 
   1 
   } 
   , 
   0 
   , 
   3 
   ) 
  
 
   
   // {0: 1, 3: 1, length: 5} 
  
 
   
   // 将2号位到数组结束,复制到0号位 
  
 
   
   let 
   i32a 
   = 
   new 
   Int32Array 
   ( 
   [ 
   1 
   , 
   2 
   , 
   3 
   , 
   4 
   , 
   5 
   ] 
   ) 
   ; 
  
 
   
   i32a 
   . 
   copyWithin 
   ( 
   0 
   , 
   2 
   ) 
   ; 
  
 
   
   // Int32Array [3, 4, 5, 4, 5] 
  
 
   
   // 对于没有部署 TypedArray 的 copyWithin 方法的平台 
  
 
   
   // 需要采用下面的写法 
  
 
   
   [ 
   ] 
   . 
   copyWithin 
   . 
   call 
   ( 
   new 
   Int32Array 
   ( 
   [ 
   1 
   , 
   2 
   , 
   3 
   , 
   4 
   , 
   5 
   ] 
   ) 
   , 
   0 
   , 
   3 
   , 
   4 
   ) 
   ; 
  
 
   
   // Int32Array [4, 2, 3, 4, 5] 
  
 
   
  数组实例的 find() 和 findIndex()
 
  
  数组实例的 
  find 
  方法,用于找出第一个符合条件的数组成员。它的参数是一个回调函数,所有数组成员依次执行该回调函数,直到找出第一个返回值为 
  true 
  的成员,然后返回该成员。如果没有符合条件的成员,则返回 
  undefined 
  。 
 
 
  
   
   [ 
   1 
   , 
   4 
   , 
   - 
   5 
   , 
   10 
   ] 
   . 
   find 
   ( 
   ( 
   n 
   ) 
   = 
   > 
   n 
   < 
   0 
   ) 
  
 
   
   // -5 
  
 
   
  
  上面代码找出数组中第一个小于 0 的成员。 
 
 
  
   
   [ 
   1 
   , 
   5 
   , 
   10 
   , 
   15 
   ] 
   . 
   find 
   ( 
   function 
   ( 
   value 
   , 
   index 
   , 
   arr 
   ) 
   { 
  
 
   
     
   return 
   value 
   > 
   9 
   ; 
  
 
   
   } 
   ) 
   // 10 
  
 
   
  
  上面代码中, 
  find 
  方法的回调函数可以接受三个参数,依次为当前的值、当前的位置和原数组。 
 
 
  
  数组实例的 
  findIndex 
  方法的用法与 
  find 
  方法非常类似,返回第一个符合条件的数组成员的位置,如果所有成员都不符合条件,则返回 
  -1 
  。 
 
 
  
   
   [ 
   1 
   , 
   5 
   , 
   10 
   , 
   15 
   ] 
   . 
   findIndex 
   ( 
   function 
   ( 
   value 
   , 
   index 
   , 
   arr 
   ) 
   { 
  
 
   
     
   return 
   value 
   > 
   9 
   ; 
  
 
   
   } 
   ) 
   // 2 
  
 
   
  
  这两个方法都可以接受第二个参数,用来绑定回调函数的 
  this 
  对象。 
 
 
  
   
   function 
   f 
   ( 
   v 
   ) 
   { 
  
 
   
     
   return 
   v 
   > 
   this 
   . 
   age 
   ; 
  
 
   
   } 
  
 
   
   let 
   person 
   = 
   { 
   name 
   : 
   'John' 
   , 
   age 
   : 
   20 
   } 
   ; 
  
 
   
   [ 
   10 
   , 
   12 
   , 
   26 
   , 
   15 
   ] 
   . 
   find 
   ( 
   f 
   , 
   person 
   ) 
   ; 
      
   // 26 
  
 
   
  
  上面的代码中, 
  find 
  函数接收了第二个参数 
  person 
  对象,回调函数中的 
  this 
  对象指向 
  person 
  对象。 
 
 
  
  另外,这两个方法都可以发现 
  NaN 
  ,弥补了数组的 
  indexOf 
  方法的不足。 
 
 
  
   
   [ 
   NaN 
   ] 
   . 
   indexOf 
   ( 
   NaN 
   ) 
  
 
   
   // -1 
  
 
   
   [ 
   NaN 
   ] 
   . 
   findIndex 
   ( 
   y 
   = 
   > 
   Object 
   . 
   is 
   ( 
   NaN 
   , 
   y 
   ) 
   ) 
  
 
   
   // 0 
  
 
   
  
  上面代码中, 
  indexOf 
  方法无法识别数组的 
  NaN 
  成员,但是 
  findIndex 
  方法可以借助 
  Object.is 
  方法做到。 
   
  数组实例的 fill()
 
  
  fill 
  方法使用给定值,填充一个数组。 
 
 
  
   
   [ 
   'a' 
   , 
   'b' 
   , 
   'c' 
   ] 
   . 
   fill 
   ( 
   7 
   ) 
  
 
   
   // [7, 7, 7] 
  
 
   
   new 
   Array 
   ( 
   3 
   ) 
   . 
   fill 
   ( 
   7 
   ) 
  
 
   
   // [7, 7, 7] 
  
 
   
  
  上面代码表明, 
  fill 
  方法用于空数组的初始化非常方便。数组中已有的元素,会被全部抹去。 
 
 
  
  fill 
  方法还可以接受第二个和第三个参数,用于指定填充的起始位置和结束位置。 
 
 
  
   
   [ 
   'a' 
   , 
   'b' 
   , 
   'c' 
   ] 
   . 
   fill 
   ( 
   7 
   , 
   1 
   , 
   2 
   ) 
  
 
   
   // ['a', 7, 'c'] 
  
 
   
  
  上面代码表示, 
  fill 
  方法从 1 号位开始,向原数组填充 7,到 2 号位之前结束。 
 
 
  
  注意,如果填充的类型为对象,那么被赋值的是同一个内存地址的对象,而不是深拷贝对象。 
 
 
  
   
   let 
   arr 
   = 
   new 
   Array 
   ( 
   3 
   ) 
   . 
   fill 
   ( 
   { 
   name 
   : 
   "Mike" 
   } 
   ) 
   ; 
  
 
   
   arr 
   [ 
   0 
   ] 
   . 
   name 
   = 
   "Ben" 
   ; 
  
 
   
   arr 
  
 
   
   // [{name: "Ben"}, {name: "Ben"}, {name: "Ben"}] 
  
 
   
   let 
   arr 
   = 
   new 
   Array 
   ( 
   3 
   ) 
   . 
   fill 
   ( 
   [ 
   ] 
   ) 
   ; 
  
 
   
   arr 
   [ 
   0 
   ] 
   . 
   push 
   ( 
   5 
   ) 
   ; 
  
 
   
   arr 
  
 
   
   // [[5], [5], [5]] 
  
 
   
  数组实例的 entries(),keys() 和 values()
 
  
  ES6 提供三个新的方法—— 
  entries() 
  , 
  keys() 
  和 
  values() 
  ——用于遍历数组。它们都返回一个遍历器对象(详见《Iterator》一章),可以用 
  for...of 
  循环进行遍历,唯一的区别是 
  keys() 
  是对键名的遍历、 
  values() 
  是对键值的遍历, 
  entries() 
  是对键值对的遍历。 
 
 
  
   
   for 
   ( 
   let 
   index of 
   [ 
   'a' 
   , 
   'b' 
   ] 
   . 
   keys 
   ( 
   ) 
   ) 
   { 
  
 
   
     console 
   . 
   log 
   ( 
   index 
   ) 
   ; 
  
 
   
   } 
  
 
   
   // 0 
  
 
   
   // 1 
  
 
   
   for 
   ( 
   let 
   elem of 
   [ 
   'a' 
   , 
   'b' 
   ] 
   . 
   values 
   ( 
   ) 
   ) 
   { 
  
 
   
     console 
   . 
   log 
   ( 
   elem 
   ) 
   ; 
  
 
   
   } 
  
 
   
   // 'a' 
  
 
   
   // 'b' 
  
 
   
   for 
   ( 
   let 
   [ 
   index 
   , 
   elem 
   ] 
   of 
   [ 
   'a' 
   , 
   'b' 
   ] 
   . 
   entries 
   ( 
   ) 
   ) 
   { 
  
 
   
     console 
   . 
   log 
   ( 
   index 
   , 
   elem 
   ) 
   ; 
  
 
   
   } 
  
 
   
   // 0 "a" 
  
 
   
   // 1 "b" 
  
 
   
  
  如果不使用 
  for...of 
  循环,可以手动调用遍历器对象的 
  next 
  方法,进行遍历。 
 
 
  
   
   let 
   letter 
   = 
   [ 
   'a' 
   , 
   'b' 
   , 
   'c' 
   ] 
   ; 
  
 
   
   let 
   entries 
   = 
   letter 
   . 
   entries 
   ( 
   ) 
   ; 
  
 
   
   console 
   . 
   log 
   ( 
   entries 
   . 
   next 
   ( 
   ) 
   . 
   value 
   ) 
   ; 
   // [0, 'a'] 
  
 
   
   console 
   . 
   log 
   ( 
   entries 
   . 
   next 
   ( 
   ) 
   . 
   value 
   ) 
   ; 
   // [1, 'b'] 
  
 
   
   console 
   . 
   log 
   ( 
   entries 
   . 
   next 
   ( 
   ) 
   . 
   value 
   ) 
   ; 
   // [2, 'c'] 
  
 
   
  数组实例的 includes()
 
  
  Array.prototype.includes 
  方法返回一个布尔值,表示某个数组是否包含给定的值,与字符串的 
  includes 
  方法类似。ES2016 引入了该方法。 
 
 
  
   
   [ 
   1 
   , 
   2 
   , 
   3 
   ] 
   . 
   includes 
   ( 
   2 
   ) 
       
   // true 
  
 
   
   [ 
   1 
   , 
   2 
   , 
   3 
   ] 
   . 
   includes 
   ( 
   4 
   ) 
       
   // false 
  
 
   
   [ 
   1 
   , 
   2 
   , 
   NaN 
   ] 
   . 
   includes 
   ( 
   NaN 
   ) 
   // true 
  
 
   
  
  该方法的第二个参数表示搜索的起始位置,默认为 
  0 
  。如果第二个参数为负数,则表示倒数的位置,如果这时它大于数组长度(比如第二个参数为 
  -4 
  ,但数组长度为 
  3 
  ),则会重置为从 
  0 
  开始。 
 
 
  
   
   [ 
   1 
   , 
   2 
   , 
   3 
   ] 
   . 
   includes 
   ( 
   3 
   , 
   3 
   ) 
   ; 
   // false 
  
 
   
   [ 
   1 
   , 
   2 
   , 
   3 
   ] 
   . 
   includes 
   ( 
   3 
   , 
   - 
   1 
   ) 
   ; 
   // true 
  
 
   
  
  没有该方法之前,我们通常使用数组的 
  indexOf 
  方法,检查是否包含某个值。 
 
 
  
   
   if 
   ( 
   arr 
   . 
   indexOf 
   ( 
   el 
   ) 
   ! 
   == 
   - 
   1 
   ) 
   { 
  
 
   
   // ... 
  
 
   
   } 
  
 
   
  
  indexOf 
  方法有两个缺点,一是不够语义化,它的含义是找到参数值的第一个出现位置,所以要去比较是否不等于 
  -1 
  ,表达起来不够直观。二是,它内部使用严格相等运算符( 
  === 
  )进行判断,这会导致对 
  NaN 
  的误判。 
 
 
  
   
   [ 
   NaN 
   ] 
   . 
   indexOf 
   ( 
   NaN 
   ) 
  
 
   
   // -1 
  
 
   
  
  includes 
  使用的是不一样的判断算法,就没有这个问题。 
 
 
  
   
   [ 
   NaN 
   ] 
   . 
   includes 
   ( 
   NaN 
   ) 
  
 
   
   // true 
  
 
   
  
  下面代码用来检查当前环境是否支持该方法,如果不支持,部署一个简易的替代版本。 
 
 
  
   
   const contains 
   = 
   ( 
   ( 
   ) 
   = 
   > 
  
 
   
     Array 
   . 
   prototype 
   . 
   includes 
  
 
   
       
   ? 
   ( 
   arr 
   , 
   value 
   ) 
   = 
   > 
   arr 
   . 
   includes 
   ( 
   value 
   ) 
  
 
   
       
   : 
   ( 
   arr 
   , 
   value 
   ) 
   = 
   > 
   arr 
   . 
   some 
   ( 
   el 
   = 
   > 
   el 
   === 
   value 
   ) 
  
 
   
   ) 
   ( 
   ) 
   ; 
  
 
   
   contains 
   ( 
   [ 
   'foo' 
   , 
   'bar' 
   ] 
   , 
   'baz' 
   ) 
   ; 
   // => false 
  
 
   
  
  另外,Map 和 Set 数据结构有一个 
  has 
  方法,需要注意与 
  includes 
  区分。 
 
 
  
  -  Map 结构的 has 方法,是用来查找键名的,比如 Map.prototype.has(key) 、 WeakMap.prototype.has(key) 、 Reflect.has(target, propertyKey) 。
  
  -  Set 结构的 has 方法,是用来查找值的,比如 Set.prototype.has(value) 、 WeakSet.prototype.has(value) 。
  
 
 
  数组实例的 flat(),flatMap()
 
  
  数组的成员有时还是数组, 
  Array.prototype.flat() 
  用于将嵌套的数组“拉平”,变成一维的数组。该方法返回一个新数组,对原数据没有影响。 
 
 
  
   
   [ 
   1 
   , 
   2 
   , 
   [ 
   3 
   , 
   4 
   ] 
   ] 
   . 
   flat 
   ( 
   ) 
  
 
   
   // [1, 2, 3, 4] 
  
 
   
  
  上面代码中,原数组的成员里面有一个数组, 
  flat() 
  方法将子数组的成员取出来,添加在原来的位置。 
 
 
  
  flat() 
  默认只会“拉平”一层,如果想要“拉平”多层的嵌套数组,可以将 
  flat() 
  方法的参数写成一个整数,表示想要拉平的层数,默认为1。 
 
 
  
   
   [ 
   1 
   , 
   2 
   , 
   [ 
   3 
   , 
   [ 
   4 
   , 
   5 
   ] 
   ] 
   ] 
   . 
   flat 
   ( 
   ) 
  
 
   
   // [1, 2, 3, [4, 5]] 
  
 
   
   [ 
   1 
   , 
   2 
   , 
   [ 
   3 
   , 
   [ 
   4 
   , 
   5 
   ] 
   ] 
   ] 
   . 
   flat 
   ( 
   2 
   ) 
  
 
   
   // [1, 2, 3, 4, 5] 
  
 
   
  
  上面代码中, 
  flat() 
  的参数为2,表示要“拉平”两层的嵌套数组。 
 
 
  
  如果不管有多少层嵌套,都要转成一维数组,可以用 
  Infinity 
  关键字作为参数。 
 
 
  
   
   [ 
   1 
   , 
   [ 
   2 
   , 
   [ 
   3 
   ] 
   ] 
   ] 
   . 
   flat 
   ( 
   Infinity 
   ) 
  
 
   
   // [1, 2, 3] 
  
 
   
  
  如果原数组有空位, 
  flat() 
  方法会跳过空位。 
 
 
  
   
   [ 
   1 
   , 
   2 
   , 
   , 
   4 
   , 
   5 
   ] 
   . 
   flat 
   ( 
   ) 
  
 
   
   // [1, 2, 4, 5] 
  
 
   
  
  flatMap() 
  方法对原数组的每个成员执行一个函数(相当于执行 
  Array.prototype.map() 
  ),然后对返回值组成的数组执行 
  flat() 
  方法。该方法返回一个新数组,不改变原数组。 
 
 
  
   
   // 相当于 [[2, 4], [3, 6], [4, 8]].flat() 
  
 
   
   [ 
   2 
   , 
   3 
   , 
   4 
   ] 
   . 
   flatMap 
   ( 
   ( 
   x 
   ) 
   = 
   > 
   [ 
   x 
   , 
   x 
   * 
   2 
   ] 
   ) 
  
 
   
   // [2, 4, 3, 6, 4, 8] 
  
 
   
  
  flatMap() 
  只能展开一层数组。 
 
 
  
   
   // 相当于 [[[2]], [[4]], [[6]], [[8]]].flat() 
  
 
   
   [ 
   1 
   , 
   2 
   , 
   3 
   , 
   4 
   ] 
   . 
   flatMap 
   ( 
   x 
   = 
   > 
   [ 
   [ 
   x 
   * 
   2 
   ] 
   ] 
   ) 
  
 
   
   // [[2], [4], [6], [8]] 
  
 
   
  
  上面代码中,遍历函数返回的是一个双层的数组,但是默认只能展开一层,因此 
  flatMap() 
  返回的还是一个嵌套数组。 
 
 
  
  flatMap() 
  方法的参数是一个遍历函数,该函数可以接受三个参数,分别是当前数组成员、当前数组成员的位置(从零开始)、原数组。 
 
 
  
   
   arr 
   . 
   flatMap 
   ( 
   function 
   callback 
   ( 
   currentValue 
   [ 
   , 
   index 
   [ 
   , 
   array 
   ] 
   ] 
   ) 
   { 
  
 
   
   // ... 
  
 
   
   } 
   [ 
   , 
   thisArg 
   ] 
   ) 
  
 
   
  
  flatMap() 
  方法还可以有第二个参数,用来绑定遍历函数里面的 
  this 
  。 
 
 
 
   end