拓展运算符的应用

拓展运算符

拓展运算符(spread)是三个点(...)。它好比rest参数的逆运算,将一个数组转为用逗号分隔的参数序列

    console.log(...[1, 2, 3]); // 1 2 3

    console.log(1, ...[2, 3, 4], 5); // 1 2 3 4 5

    console.log([...document.querySelectorAll('div')]); //) [div#app, div#nav.nav, div, div, div, div]

该运算符主要用于函数调用

    function pushArray(array, ...items) {
        array.push(...items);
    }

    function add(x, y) {
        return x + y
    }

    let numbers1 = [4, 66]
    console.log(add(...numbers1)); //70
    pushArray(numbers1, ...[1, 2, 3])
    console.log(numbers1);// [4, 66, 1, 2, 3]

上面代码中,array.push(...items)和add(...numbers1)这两行,都是函数的调用,它们都使用了拓展运算符。该运算符将一个数组,变为参数序列

拓展运算符与正常的函数参数结合使用

    function f(v, w, x, y, z) {
        console.log(v, w, x, y, z)
    }
    const args = [0, 1];

    f(-1, ...args, 2, ...[3]); // -1 0 1 2 3

拓展运算符后面还可以放置表达式

    let x = 1;
    const arr = [...(x > 0 ? ['a'] : []), 'b'];
    console.log(arr);//["a", "b"]

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

console.log([...[], 1]);// [1]

替代函数的apply方法

    //ES5写法
    function f1(x, y, z) {
        console.log(x, y, z)
    }
    var args1 = [1, 2, 3]
    f1.apply(null, args1); // 1 2 3
    //ES6写法
    function f2(x, y, z) {
        console.log(x, y, z)
    }
    var args2 = [4, 5, 6]
    f2(...args2); //4 5 6

一个:拓展运算符取代apply的实际例子,应用Math.max方法,简化求出一个数组最大元素的写法

    //ES5写法
    console.log(Math.max.apply(null, [10, 20, 30]));// 30
    //ES6写法
    console.log(Math.max(...[10, 20, 30]));// 30
    //等同于
    console.log(Math.max(10, 20, 30));// 30

由于JavaScript不提供求数组最大元素的函数,所以只能套用Math.max函数,将数组转为一个参数序列,然后求最大值,有了拓展运算符以后,可以直接使用Math.max了

    //ES5写法
    var arr1 = [1, 2, 3];
    var arr2 = [4, 5, 6];
    Array.prototype.push.apply(arr1, arr2);
    console.log(arr1); //[1, 2, 3, 4, 5, 6]
    //ES6写法
    let arr1 = [1, 2, 3];
    let arr2 = [4, 5, 6];
    arr1.push(...arr2);
    console.log(arr1); // [1, 2, 3, 4, 5, 6]

另外一个

    //ES5写法
    var date1 = new(Date.bind.apply(Date, [null, 2018, 1, 1]));
    console.log(date1); // Thu Feb 01 2018 00:00:00 GMT+0800 (中国标准时间)
    //ES6写法
    let date2 = new Date(...[2018, 1, 1]);
    console.log(date2); // Thu Feb 01 2018 00:00:00 GMT+0800 (中国标准时间)

拓展运算符的应用

复制数组

数组时复合的数据类型,直接复制的话,只是复制了指向底层数据结构的指针,而不是克隆了一个全新的数组(也就是说修改其中一个数组,另一个也会改变,因为两个指针同时指向一份数据)

    //ES6中的数组克隆
    const arr1 = [1, 2, 3];
    //写法1
    const arr2 = [...arr1];
    //写法2
    const [...arr3] = arr1;
    arr3[0] = 0;
    console.log(arr1); //[1, 2, 3]
    console.log(arr2); //[1, 2, 3]
    console.log(arr3); //[0, 2, 3]

合并数组

    let arr1 = [1, 2];
    let arr2 = [3];
    let arr3 = [4, 5];

    let arr5;
    let arr6;
    //ES5合并
    arr5 = arr1.concat(arr2, arr3);
    console.log(arr5); // [1, 2, 3, 4, 5]
    //ES6合并
    arr6 = [...arr1, ...arr2, ...arr3];
    console.log(arr6); // [1, 2, 3, 4, 5]

与结构赋值结合

    function arr(list, a, ...rest) {
        list = [a, ...rest];
        return list
    }

    console.log(arr([], "a", ...["b", "v"])); //["a", "b", "v"]

需要注意的是,如果将拓展运算符用于数组赋值,只能放在参数的最后一位,否则报错

字符串
使用拓展运算符将字符串转为数组

    console.log([...'Hello,Mr']); //["H", "e", "l", "l", "o", ",", "M", "r"]

实现Iterator接口的对象

任何Iterator接口的对象,都可以用拓展运算符转为真正的数组

    let nodeList = document.querySelectorAll('div');
    let array = [...nodeList];
    console.log(array); //[div#app, div#nav.nav, div, div, div, div]

上面代码中。querySelectorAll方法返回的是一个NodeList对象。它不是数组,而是类似数组的对象,使用拓展运算符可以将其转为真正的数组,原因在于NodeList对象实现了Iterator

Map和Set结构,Generator函数

拓展运算符内部调用的是数组结构的Iterator接口,因此只要具有Iterator接口的对象,都可以使用拓展运算符

Map结构

    let map = new Map([
        [1, 'a'],
        [2, 'b'],
        [3, 'c']
    ])
    let arr = [...map.keys()];
    console.log(arr); // [1, 2, 3]

Generator函数运行后,返回一个遍历器对象,因此也可以使用拓展运算符

    const go = function*() {
        yield 1;
        yield 2;
        yield 3;
    }
    //变量go是一个Generator函数,执行后返回的是一个遍历器对象,对这个遍历器对象执行拓展运算符,就会将内部遍历得到的值,转为一个数组
    let arr = [...go()];
    console.log(arr);//[1, 2, 3]

你可能感兴趣的:(拓展运算符的应用)