数组扩展

扩展运算符(spread)是三个点(...)。它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列。
扩展运算符后面还有可以跟其他表达式

let arr = [... 1>2? ['No'] : ['Yes'],'b'];
console.log(...arr);  // Yes b

如果扩展运算符后面是一个空数组,则不产生任何效果

[...[], 1]
// [1]

//扩展运算符与apply
{
  let args = [23,45,14,56,4];
  let args1 = [4,2,8,6];
  //es5
  Math.max.apply(null,args);
  Array.prototype.push.apply(args1,args);
  //es6
  Math.max(...args);
  args1.push(...args);
}

扩展运算符的应用

合并数组,解构赋值结合

 let foo = [1,2,3];
  let baz = ['bmw','benzi','audi'];
  let target = [];

  //es5
  target.concat(foo,baz);
  let first = baz[0];
  let others = baz.slice(1);

  //es6
  target = [...foo,...baz];
 {
     let first ,others;
 ([first,...others] = baz);
 console.log(first); // 'bmw'
 console.log(others); // ['benzi','audi']
  }

如果将扩展运算符用作数组赋值,则只能放在参数最后一位

const [...butLast, last] = [1, 2, 3, 4, 5];
// 报错

const [first, ...middle, last] = [1, 2, 3, 4, 5];
// 报错

将字符串分割成数组

[...'benzi'];
// ['b','e','n','z','i'];
// 等价于
Array.from('benzi');

面的写法,有一个重要的好处,那就是 能够正确识别32位的Unicode字符

 'x\uD83D\uDE80y'.length // 4
[...'x\uD83D\uDE80y'].length // 3

**JavaScript会将32位Unicode字符,识别为2个字符,采用扩展运算符就没有这个问题 **
凡是涉及到 **操作32位 Unicode 字符的函数 **,都有这个问题。因此,最好都用扩展运算符改写。

let str = 'x\uD83D\uDE80y';

str.split('').reverse().join('')
// 'y\uDE80\uD83Dx'

[...str].reverse().join('')
// 'y\uD83D\uDE80x'

ps:Array.from也可与实现扩展运算符的以上功能
如果不用扩展运算符,字符串的reverse操作就不正确。

扩展运算符可以将实现了 Iterator 接口的对象转换为数组

[...document.querySelectorAll('div')];

ps: Array.from方法将arrayLike转为真正的数组

Map 和 Set 结构,Generator 函数

扩展运算符可以将以上数据结构或者函数转换为数组,因为这些数据结构都实现了Iterator接口

 var go = function*(){
  yield 1;
  yield 2;
  yield 3;
};

[...go()] // [1, 2, 3]

Array.from()

Array.from方法用于将 两类对象转为真正的数组类似数组的对象(array-like object)和 可遍历(iterable)的对象(包括ES6新增的数据结构Set和Map)

let arrlike = {
    0: 'bmw',
    1: 'benzi',
    2: 'audi',
    length: 3
};

console.log(Array.from(arrlike));  // [ 'bmw', 'benzi', 'audi' ]

// NodeList对象
let ps = document.querySelectorAll('p');
Array.from(ps).forEach(function (p) {
  console.log(p);
});

// arguments对象
function foo() {
  var args = Array.from(arguments);
  // ...
}

如果参数是一个真正的数组,Array.from会返回一个一模一样的 新数组

let a = [1, 2, 3];
// undefined
let b = Array.from(a);
// undefined
a==b;
// false
a === b
// false
a[3] = 4;
//    4
a
//    (4) [1, 2, 3, 4]
b
//     (3) [1, 2, 3]

任何有 __length属性__的对象,都可以通过Array.from方法转为数组,而此时 扩展运算符就无法转换。

let arr0 =Array.from({length:3});
console.log(arr0);    // [ undefined, undefined, undefined ]

let a = {0:'a',b:'b',2:'c',length:4}
Array.from(a); // (4) ["a", undefined, "c", undefined]

Array.from还可以接受 第二个参数,作用类似于数组的map方法,用来对每个元素进行处理,将处理后的值放入返回的数组

Array.from(arrayLike, x => x * x);
// 等同于
Array.from(arrayLike).map(x => x * x);

let arr0 =Array.from({length:3},x=>x || 3);
console.log(arr0); // [ 3, 3, 3 ]

还可以传入Array.from的第三个参数,用来绑定this。

Array.of()

Array.of方法用于将一组值,转换为数组。

Array.of(3, 11, 8) // [3,11,8]
Array.of(3) // [3]
Array.of(3).length // 1

该方法是弥补数组构造函数Array()的不足。因为参数个数的不同,会导致Array()的行为有差异。
Array.of基本上可以用来替代Array()或new Array(),并且不存在由于参数不同而导致的重载。它的行为非常统一。

Array.of() // []
Array.of(undefined) // [undefined]
Array.of(1) // [1]
Array.of(1, 2) // [1, 2]

Array.of总是 返回参数值组成的数组。如果没有参数,就返回一个空数组

数组实例的 find() 和 findIndex()

find方法,用于找出 第一个符合条件 的数组成员。它的参数是一个回调函数,所有数组成员依次执行该回调函数,直到找出第一个返回值为true的成员,然后返回该成员。如果没有符合条件的成员,则返回undefined。

[1,2,3,4].find((n)=>n>2);
//3
[1,2,3,4].findIndex((n)=>n>2);
//2

findIndex()方法返回的是第一个满足条件的 元素索引,如果没有找到返回-1
find,findIndex方法的 回调函数可以接受三个参数,依次为当前的值、当前的位置和原数组。这两个方法都可以接受 第二个参数,用来绑定回调函数的this对象。
ps: 另外,这两个方法都可以发现NaN,弥补了数组的IndexOf方法的不足。

 [NaN].indexOf(NaN)
// -1
[1,3,NaN].find(x => Object.is(NaN,x)); //NaN

fill()方法

fill方法使用给定值,填充一个数组。如果数组有原始值,填充的值会覆盖掉数组原来的值,该方法接受三个参数,第一个参数是填充数组的值,第二个,第三个参数分别是填充的开始位置(包含)和填充结束位置(不包含)。若后面两个参数缺省,则会填充整个数组。

['a', 'b', 'c'].fill(7, 1, 2) ; // ['a',7,'b']

includes()

表示某个数组是否包含给定的值

[1, 2, NaN].includes(NaN) // true

该方法的第二个参数表示搜索的起始位置,默认为0。如果第二个参数为负数,则表示倒数的位置,如果这时它大于数组长度(比如第二个参数为-4,但数组长度为3),则会重置为从0开始。

[1, 2, 3].includes(3, 3);  // false
[1, 2, 3].includes(3, -1); // true

另外,Map 和 Set 数据结构有一个has方法,需要注意与includes区分。

数组空位

ES5中的部分数组的方法都会忽略空位, ES6 则是明确将空位转为undefined。
Array.from方法,扩展运算符会将数组的空位,转为undefined,也就是说,这个方法不会忽略空位。

Array.from(['a',,'b'])
// [ "a", undefined, "b" ]

[...['a',,'b']]
// [ "a", undefined, "b" ]

copyWithin()会连空位一起拷贝。

[,'a','b',,].copyWithin(2,0) // [,"a",,"a"]

fill()会将空位视为正常的数组位置

new Array(3).fill('a') // ["a","a","a"]

for...of循环也会遍历空位。
entries()、keys()、values()、find()和findIndex()会将空位处理成undefined。

posted @ 2017-08-15 09:43  joe_ice  阅读(218)  评论(0)    收藏  举报