美文网首页
ES6学习之- 数组的扩展

ES6学习之- 数组的扩展

作者: 尤小小 | 来源:发表于2017-09-21 01:08 被阅读26次

    Part3 数组的扩展

    3.1 扩展运算符和数组的解构赋值

    (1)扩展运算符是三个点 ...,扩展运算符主要用于函数调用,它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列。

    • 合并数组

    arr.push(...arr1);

    let arr = [1, 2, 3];
    arr.push([4, 5, 6]); 
    
    arr
    // [1, 2, 3, Array(3)]
    

    我们想把[4, 5, 6]数组通过arr.push()方式合并到arr上;显然我们这样做没有成功。es5也有可以合并数组的方法通过arr.concat([4, 5, 6]) 来实现, es6添加的扩展运算符可以实现,可读性更好。

    let arr1 = [4, 5, 6];
    arr.push(...arr1);
    arr
    // [1, 2, 3, Array(3), 4, 5, 6]
    

    上面的例子,是扩展运算符的一个简单运用,简单理解就是把数组拉平。arr.push(...arr1)使用了扩展运算符。将数组numbers展开后,一个个插入到arr数组里。

    • 扩展运算符可以将nodeList类数组对象转为真正的数组
    [...document.querySelectorAll('div')]
    // [<div>, <div>, <div>]
    

    querySelectorAll方法返回的是一个nodeList对象。nodeList对象不是数组,而是一个类似数组的对象。这时,扩展运算符可以将其转为真正的数组,原因就在于NodeList对象实现了 Iterator 。

    (2)扩展运算符与解构赋值结合

    {
      const [first, ...rest] = [1, 2, 3, 4, 5];
      first // 1
      rest  // [2, 3, 4, 5]
    }
    
    {
      const [first, ...rest] = ["foo"];
      first  // "foo"
      rest   // []
    }
    

    (3)扩展运算符用于数组赋值,只能放在参数的最后一位,否则会报错

    {
    const [...butLast, last] = [1, 2, 3, 4, 5];
    // 报错 :Rest element must be last element
    
    const [first, ...middle, last] = [1, 2, 3, 4, 5];
    // 报错:Rest element must be last element
    }
    

    数组的解构赋值在主站中的一个简单应用

    let [obj, $UI] = [{}, $('body')];
    
    // 等同于
    let obj = {};
    let $UI = $('body');
    

    3.2 Array.from()

    es6对数组扩展Array.from方法,用于将类数组转换真正的数组,并且对数组里面的元素遍历操作,再返回一个新数组。

    Array.from(arrayLike, => )

    Array.from方法,可以将类数组对象转为真正的数组。

    为什么要es6要扩展Array.from()? 是因为扩展运算符不能展开类数组,会直接报错。当然es5也可以通过[].slice.call(arrayLike)将arrayLike转为真正的数组,但是使用起来并不是很简洁方便,于是es6对数组扩展Array.from方法,可以直接将arrayLike转为真正的数组。

    let arrayLike = {
        '0': 'a',
        '1': 'b',
        '2': 'c',
        length: 3
    };
    
    // 报错: Cannot spread non-iterable object.
    let arr = [...arrayLike];
    
    // ES5的写法:将类数组转化为数组
    var arr2 = [].slice.call(arrayLike); 
    
    [...arr2] // ['a', 'b', 'c']
    

    Array.from方法可以将具有具有Iterator接口的类似数组的对象转换为对象,扩展运算符背后调用的是遍历器接口,本质特征只有一点,任何有length属性的对象,都可以通Array.from方法转为数组。

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

    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.from还可以传入第三个参数。当map函数里面用到了this关键字,Array.from接受的第三个参数,用来绑定map函数中this指向的对象。

    {
      let obj = {
        handle (n){
          return n + 2;
        },
        newArr () {
            let newArr = Array.from([1, 2, 3, 4, 5], (x) => {
                return this.handle(x);
          });
          console.log(newArr);  //  [3, 4, 5, 6, 7]   
        }
      };
    
      obj.newArr();
    }
    

    3.3 Array.of

    Array.of方法用于将一组值,转换为数组。Array.of基本上可以用来替代Array()或new Array(),并且不存在由于参数不同而导致的重载。它的行为非常统一。

    Array.of(item1, item2, ...)

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

    es5�的Array方法也可以实现,为什么有要扩展一个Array.of方法呢?

    Array()  // []
    Array(3) // [, , ,]
    Array(3, 11, 8) // [3, 11, 8]
    

    因为当Array方法没有参数表示创建一个新数组;一个参数时,实际上是制定数组的长度,表示创建一个以参数长度的数组。几种情况返回的结果不一致。es6针对这个问题给数组扩展了Array.of方法。

    3.4 find(), findIndex()

    从语义上来看,这两个都是查找,一个是按照数组成员找,一个是按照数组成员的索引来找。

    arr.find((当前的值, 前的位置, 原数组) => {})

    arr.findIndex((当前的值, 当前的位置, 原数组) => {})

    find方法的回调函数可以接受三个参数,依次为当前的值、当前的位置和原数组。

    [1, 5, -10, 15].find((value) => value < 0);
    // -10
    
    [1, 5, -10, 15].find((value, index) => value < index );
    // -10
    
    [1, 5, -10, 15].find((value, index, arr) => value > 9 ); 
    // 15
    
    

    findIndex方法的用法与find方法非常类似,返回第一个符合条件的数组成员的位置,如果所有成员都不符合条件,则返回-1。也可以接受三个参数,依次为当前的值、当前的位置和原数组。

    [1, 5, -10, 15].findIndex((value) => value > 9); // 3
    
    [1, 5, -10, 15].findIndex((value, index) => value > 1 && index >= 1); // 1
    
    [1, 5, -10, 15].findIndex((value, index, arr) =>  value > 9 && index > 1 && arr.length > 3); // 3
    

    3.5 includes()

    includes方法与字符串的includes方法类似。用于搜索数组中是否包含某个值,若有返回true,若没有返回false。

    在es6之前数组有indexOf方法,用于检查是否包含某个值,若包含返回该值首次出现的位置,若不包含返回-1。

    indexOf方法有两个缺点:

    • 一是不够语义化,它的含义是找到参数值的第一个出现位置,所以要去比较是否不等于-1,表达起来不够直观。
    • 二是,它内部使用严格相等运算符(===)进行判断,这会导致对NaN的误判。
    [NaN].indexOf(NaN)
    // -1
    

    es6为了避免这个问题,给数组扩展了includes方法,includes使用的是不一样的判断算法。

    [NaN].includes(NaN)
    // true
    

    react项目中单选反选功能中的includes()应用

    constructor(props) {
      super(props);
      this.state = {selected: []};
    }
    
    handleRowSelect(i) {
      let selected = this.state.selected;
      if (selected.includes(i)) {
        let itemIdx = selected.indexOf(i);
        selected.splice(itemIdx, 1);
      } else {
        selected.push(i);
      }
      this.setState({selected: selected});
    }
    

    记得第一节字符串的扩展中includes()对于ios8以下还有兼容性问题,目前不建议在主站中使用。

    3.6 keys(), values(), entries()

    es6 给数组扩展了三个新方法keys(), values(), entries(),用于遍历数组。它们的区别是keys()是对键名的遍历、values()是对键值的遍历,entries()是对键值对的遍历。使用for...of循环进行遍历。

    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"
    

    Chrome 还未实现Array.prototype.values()

    3.7 fill()

    fill方法使用给定值,填充一个数组。fill方法三个参数,分别用于,要填充的元素、指定填充的起始位置和结束位置。

    ['a', 'b', 'c'].fill(7)
    // [7, 7, 7]
    
    new Array(3).fill(7)
    // [7, 7, 7]
    
    ['a', 'b', 'c'].fill(7, 2)
    // ["a", "b", 7]
    
    ['a', 'b', 'c'].fill(7, 1, 2)
    // ['a', 7, 'c']
    

    上面代码表明,fill方法用于空数组的初始化非常方便。数组中已有的元素,会被全部抹去。

    小结

    • 扩展运算符主要用于函数调用

    • 数组的解构赋值

    • Array.from() 将类数组转化为数组

    • find(), findIndex() 查找数组成员

    • includes() 搜索数组中是否包含某个值

    相关文章

      网友评论

          本文标题:ES6学习之- 数组的扩展

          本文链接:https://www.haomeiwen.com/subject/tiwasxtx.html