简述ES6新特性③

1,150 阅读5分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第28天,点击查看活动详情

ES6新特性③

rest参数

ES6引入rest参数,用户获取函数的实参,用来代替arguments

1. 先来看看ES5获取实参列表的方式

        function date() {
            console.log(arguments);
        }
        date('A', 'B', 'C');

Arguments(3),arguments接收完是以伪数组形式保存的,不能用数组有关的方法

2. ES6的rest参数
格式: ...标识符
这个rest参数接收完实参是以数组形式保存的
也就是说rest参数可以使用filtersomeeverymap等数组方法

        function fn(...args) {
            console.log(args);
        }
        fn('A','B','C');

3. rest参数必须要放到参数最后
很简单,如果不把rest参数放最后,那么在rest参数后面的参数都失效啦

        function fn2(a, b, ...abc) {
            console.log(a);
            console.log(b);
            console.log(abc);
        }
        fn2(1, 2, 3, 4, 5, 6); // 1,2 Array(4)

spread扩展运算符

... 是扩展运算符, 它能将 数组 转换为逗号分割的 参数序列

声明一个数组

    const tfboys = ['易烊千玺', '王源', '王俊凯'];

声明一个函数

    function fn() {
            console.log(arguments);
        }
        
    fn(tfboys);
    fn(...tfboys);

当tfboys整体做为一个数组传入时,arguments的长度为1

利用扩展运算符将tfboys这个数组,转换为了'易烊千玺', '王源', '王俊凯'这样一个参数序列,等同于fn('易烊千玺', '王源', '王俊凯'); arguments的长度为3

扩展运算符运用

1.将伪数组转为真正的数组

        const divs = document.querySelectorAll('div');
        console.log(divs); // NodeList(3)

        const divArr = [...divs];
        console.log(divArr); // [div,div,div]

这里能也能把伪数组arguments转换成数组,但是呢,因为rest参数的存在,就没必要对它动手了

2.数组的克隆

        const dzq = ['G', 'E', 'M'];
        const jyz = [...dzq];
        console.log(jyz); // ['G', 'E', 'M']

这个拷贝是浅拷贝,如果拷贝对象中有引用类型的数据,那么只会拷贝引用数据的值,也就是地址,不会拷贝对象

3.数组的合并

        const arr1 = ['AA', 'BB'];
        const arr2 = ['CC', 'DD'];

以前合并数组我们是这么写的:

    const arr3 = arr1.concat(arr2);

现在可以这么写:

        const arr4 = [...arr1, ...arr2];
        console.log(arr4); // ['AA', 'BB','CC', 'DD']

Symbol的基本使用

ES6 引入了一种新的原始数据类型Symbol,表示独一无二的值。它是JavaScript语言的第七种数据类型,是一种类似于字符串的数据类型。
(string,number,boolean,undefined,null,object,Symbol)

Symbol特点:

  1. Symbol的值是唯一的,用来解决命名冲突问题
  2. Symbol的值不能与其他数据进行运算
  3. Symbol定义的对象属性不能使用 for...in循环遍历,但是可以使用Reflect.ownKeys来获取对象的所有键名

Symbol 值通过Symbol()函数生成。
这就是说,对象的属性名现在可以有两种类型,一种是原来就有的字符串,另一种就是新增的 Symbol 类型。
凡是属性名属于 Symbol 类型,就都是独一无二的,可以保证不会与其他属性名产生冲突。

注意,Symbol函数前不能使用new命令,否则会报错。这是因为生成的 Symbol 是一个原始类型的值,不是对象。也就是说,由于 Symbol 值不是对象,所以不能添加属性。基本上,它是一种类似于字符串的数据类型。

        //创建Symbol
        let s = Symbol();
        console.log(s, typeof s); // Symbol(),'symbol'
        let s2 = Symbol('ONE PIECE');
        let s3 = Symbol('ONE PIECE');

Symbol函数可以接受一个字符串作为参数,表示对 Symbol 实例的描述,主要是为了在控制台显示,或者转为字符串时,比较容易区分。

    console.log(s2 === s3); // false

注意,Symbol函数的参数只是表示对当前 Symbol 值的描述,因此相同参数的Symbol函数的返回值是不相等的

        //Symbol.for创建
        let s4 = Symbol.for('ONE PIECE');
        let s5 = Symbol.for('ONE PIECE');
        console.log(s4 === s5); //true
        
        //不能与其他数据类型运算
        // let result = s + 100; //报错
        // let result = s > 100; //报错
        // let result = s + s; //报错

Symbol创建对象属性

Symbol的其中一个使用场景就是给 对象中添加方法 up、down

        let game = {
            name: '合金弹头',
            fn1: function () {},
            fn2: function () {}
        };

game.fn1 = function () {}
我们感觉好像可以这么给对象里面添加方法,但是会有一定的风险,因为你不知道对象里边到底有没有这个方法fn1,想快速完成这事还是有点麻烦,如果对象的结构简单,我们很快就能找出来,如果结构复杂,可能要花很长时间,才能决定下一步该怎么命名

所以我们就能借助Symbol来完成这种事情,就变得非常简单高效且安全

        //声明一个对象
        let methods = {
            fn1: Symbol(),
            fn2: Symbol()
        };

        game[methods.fn1] = function () {
            console.log("射击");
        }
        game[methods.fn2] = function () {
            console.log("蹲下");
        }
        //原本我就有fn1方法和fn2方法,利用上面那种方式,又安全地向里面加了两个方法
        console.log(game);

image.png

一些注意事项

注意,Symbol 值作为对象属性名时,不能用点运算符。

        const mySymbol = Symbol();
        const a = {};

        a.mySymbol = 'Hello!';
        a[mySymbol] // undefined
        a['mySymbol'] // "Hello!"

上面代码中,因为点运算符后面总是字符串,所以不会读取mySymbol作为标识名所指代的那个值,导致a的属性名实际上是一个字符串,而不是一个 Symbol 值。

👉 同理,在对象的内部,使用 Symbol 值定义属性时,Symbol 值必须放在方括号之中。👈

        let s = Symbol();

        let obj = {
          [s]: function (arg) { ... }
        };
        
        
        obj[s](123);

上面代码中,如果s不放在方括号中,该属性的键名就是字符串s,而不是s所代表的那个 Symbol 值。
采用ES6的对象写法,上面代码的obj对象可以写得更简洁一些

        let obj = {
          [s](arg) { ... }
        };