ES6 前端必学ES6,看完掌握新特性

Posted IT_Holmes

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ES6 前端必学ES6,看完掌握新特性 相关的知识,希望对你有一定的参考价值。

1.ES6 rest 参数

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

<script>
    //ES6 引入rest参数,用来获取函数的实参,用来代替arguments。
    //arguments和rest参数,得到的结果不同,前者是对象,后者是数组。
    function data(){
        console.log(arguments);
    }
    data('zhangsan','lisi','wangwu');

    function jiantou(...args){
        console.log(args);
    }
    jiantou('zhangsan','wangwu','lisi');
</script>

arguments和rest参数,得到的结果不同,前者是对象,后者是数组。
见下图结果:
在这里插入图片描述
注意:

rest参数必须要放到参数最后。

在这里插入图片描述

2. ES6 扩展运算符

2.1 ES6 简介

[ … ] 扩展运算符能将数组转换为逗号分隔的参数序列。

扩展运算法和rest参数,不一样,扩展运算符常用的就是将一个数组内容,有顺序的传入到一个函数方法中。

2.2 应用

1. 数组合并

<script>
    //数组合并
    const s = ['1','2','3','4'];
    const q = ['5','6','7','8'];
    const m = [...s,...q];
    console.log(m);
</script>

2. 数组克隆

<script>
    //数组克隆
    const a = ['zhangsan','lisi','wangwu'];
    const b = [...a];
    console.log(b);
</script>

3. 将伪数组转化为真正的数组

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div></div>
    <div></div>
    <div></div>
    <script>
        //这里的divs是伪数组,可以看的出它的类别是节点列表nodelist。
        const divs = document.querySelectorAll('div');
        console.log(divs);

        //转化为数组
        const divArr = [...divs];
        console.log(divArr);
    </script>
</body>
</html>

在这里插入图片描述

3. ES6 Symbol 数据类型

在ES6中,Symbol表示独一无二的值,也是ES6推出的第七种数据类型。Symbol和字符串不同!

3.1 Symbol两种创建方式

1. 直接Symbol() 来创建Symbol对象。这是通过调用函数来创建Symbol对象。

<script>
    let s = Symbol();
    let s2 = Symbol('张三');
    let s3 = Symbol('张三');
    console.log(s2 === s3);
</script>

这里的两个张三是不同的!

2. 使用Symbol.for方法来创建Symbol对象。和上面不同这是通过函数对象来创建Symbol。

<script>
    let s = Symbol.for("zhangsan");
    let s2 = Symbol.for("zhangsan");
    console.log(s === s2);
</script>

而使用Symbol.for创建的相同值,是一样的!!

3.2 Symbol注意事项 7个数据类型

注意:
Symbol定义的变量不能与其他数据进行运算。

7个数据类型:
记忆小技巧:
USONB (you are so niubility)

u : undefined
s : String Symbol
o : Object
n : null number
b : boolean

3.3 给对象,添加Symbol的两种属性

方式一:

向对象中添加另一个对象的属性值为Symbol的方法。

<script>
    let game = {
        up:function(){
            console.log("game");
        },
        down:function(){
            console.log("game2");
        }
    };  
    //向game中添加methods的属性值
    let methods = {
        up:Symbol(),
        down:Symbol()
    };
    game[methods.up] = function(){
        console.log("我可以改变形状");
    };
    game[methods.down] = function(){
        console.log("我可以快速下降");
    };
    console.log(game);
</script>

方式二:

直接使用[]添加Symbol的对象属性。

<script>
    //直接使用[]添加Symbol的对象属性。
    let game = {
        name:"英雄联盟",
        [Symbol('角色')]:function(){
            console.log("我是亚索");
        },
        [Symbol('我哥哥是谁')]:function(){
            console.log("是永恩啊");
        }

    }
</script>

4. Symbol 内置属性

4.1 hasInstance 与 instanceof

instanceof的用途是判断一个对象是否在某个对象原型链上。或者说判断一个对象是某个对象的实例。

当其他对象使用instanceof运算符,判断是否为对象的实例时,会调用这个方法。

例如:

<script>
    class Person{
        //hasInstance可以自己来控制类型检测
        static [Symbol.hasInstance](param){
            console.log(param);
            console.log("我被用来检测类型");
        };
    }
    let o = {};

    console.log(o instanceof Person);
</script>

4.2 isConcatSpreadable 与 concat

对象的Symbol.isConcatSpreadable属性等于的是一个布尔值,表示该对象用于concat(Array.prototype.concat())时,是否展开。

<script>
    const arr = [1,2,3];
    const arr2 = [4,5,6]; 
    //通过设置isConcatSpreadable来决定,合并后是否展开。
    arr2[Symbol.isConcatSpreadable] = false;
    console.log(arr.concat(arr2));
</script>

4.3 其他Symbol的内置属性

在这里插入图片描述
在这里插入图片描述
这些属性都是Symbol的内置属性,而他们的整体来作为对象的属性去设置,来改变对象在特定场景下面的表现。

5. 迭代器

迭代器(Iterator)是一种接口,为各种不同的数据结构提供统一的访问机制。 任何数据结构只要部署了Iterator接口,就可以完成遍历操作。

在ES6中,一个新的遍历命令for … of循环,iterator接口主要供for … of 来使用。

以下的数据都可以使用for … of :
在这里插入图片描述
注意:
for in 遍历的是键名。
for of 遍历的是键值。

<script>
    const a = ['英雄联盟','穿越火线','CSGO'];
    //使用for in 和for of来遍历。
    //for in 遍历的是键名
    for(let b in a){
        console.log(b);
    }
    //for of 遍历的是键值
    for(let c of a){
        console.log(c);
    }
    console.log(a);
</script>

可以自己打印一下,查看Iterator的接口:

在这里插入图片描述
在这里插入图片描述

Iterator (迭代器)的工作原理:
在这里插入图片描述
关键是看next指针,我们可以打印第一个next指针看看。

<script>
    const a = ['英雄联盟','穿越火线','CSGO'];
    let iterator = a[Symbol.iterator]();
    //打印一下迭代器,看看有什么内容
    console.log(iterator)
    //打印第一个next的内容值
    console.log(iterator.next());
    //打印第二个next的内容值
    console.log(iterator.next());
    //打印第三个next的内容值
    console.log(iterator.next());
  	//没有内容时,就是显示undefined,并且done对象显示true,表示已经完成。
    console.log(iterator.next());
</script>

在这里插入图片描述

6. 迭代器自定义遍历对象

通过使用迭代器自定义遍历数据,自定义就是按照自己的想法来遍历对象或者对象内的数据。

例如:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script>
        const a = {
            name:"zhangsan",
            status:[
                'jiankang',
                'shengbing',
                'touteng',
                'ganmao'
            ],
            //给对象声明iterator接口方法
            [Symbol.iterator](){
                //声明索引变量
                let index = 0;
                return {
                    next:() => {
                        if(index < this.status.length){
                            const result =  {value:this.status[index],done:false};
                            //下标自增
                            index++;
                            return result;
                        }else{
                            return {value: undefined,done:true};
                        }
                    }
                }
            }
        }
        //遍历status中的内容。
        for(let v of a){
            console.log(v);
        }
    </script>
</body>
</html>

7. ES6 生成器(异步编程)

7.1 生成器 简介

生成器其实就是一个特殊的函数,主要作用就是异步编程。

生成器,加上“ * ” 号。

调用next()方法来打印下面案例:

<script>
    //生成器,加上“ * ” 号。
    function * gen(){
        console.log("你好。");
    }
    let ing = gen();
    // 这样的函数,普通的console.log()打印是不行的,必须调用next()方法才可以。
    //为什么调用next方法呢,可以打印一下ing,查看他的结构。
    ing.next();
</script>

7.2 生成器 yield

yield可以算作是函数代码的分隔符。

<script>
    //生成器,加上“ * ” 号。
    function * gen(){
        //yield可以算作是函数代码的分隔符。
        console.log("第一块领域");
        yield '我分割了第一块领域和第二块领域。';
        console.log("第二块领域");
        yield '我分割了第二块领域和第三块领域。';
        console.log("第三块领域");
        yield '我分割了第三块领域和第四块领域。';
        console.log("第四块领域");
    }
    let i = gen();
    //这里yield的作用体现出来了,就可以一一进行执行。
    i.next();//执行一块领域
    i.next();//执行二块领域
    i.next();//执行三块领域
    i.next();//执行四块领域
</script>

也可以打印i.next()方法,来查看对象value和done的值。如下:

<script>
    //生成器,加上“ * ” 号。
    function * gen(){
        //yield可以算作是函数代码的分隔符。
        console.log("第一块领域");
        yield '我分割了第一块领域和第二块领域。';
        console.log("第二块领域");
        yield '我分割了第二块领域和第三块领域。';
        console.log("第三块领域");
        yield '我分割了第三块领域和第四块领域。';
        console.log("第四块领域");
    }
    let i = gen();
    //这里yield的作用体现出来了,就可以一一进行执行。
    console.log(i.next());//执行一块领域
    console.log(i.next());//执行二块领域
    console.log(i.next());//执行三块领域
    console.log(i.next());//执行四块领域
    //也可以打印i.next()方法,来查看对象value和done的值。
</script>

7.3 生成器函数参数

生成器的参数大体分为两种,正常的携带参数 和 next方法传入实参。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script>
        function * gen(arg){
            console.log(arg);
            let one = yield '111';
            console.log(one);
            let two = yield '222';
            console.log(two);
            let three = yield '333';
            console.log(three);
        }

        //正常的携带参数
        let iter = gen('AAA');
        console.log(iter.next());

        //next方法是可以传入实参的!
        //这里传入的BBB将作为第一个yield语句的返回结果,我们在上面打印了一下yield '111',查看结果。
        console.log(iter.next('BBB'));

        //这里传入的CCC将作为第二个yield语句的返回结果。
        console.log(iter.next('CCC'));
        
        //这里传入的DDD将作为第三个yield语句的返回结果。
        console.log(iter.next('DDD'));
    </script>
</body>
</html>

7.4 生成器的使用

使用生成器来依次那个调用相应函数的案例,来表现异步编程思想。

案例一:简单的异步

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script>
        let one = ()=>{
            setTimeout(()=>{
                console.log("一秒后。");
                iter.next();
            },1000)
        }
        let two = ()=>{
            setTimeout(()=>{
                console.log("二秒后。");
                iter.next();
            },2000);
        }
        let three = ()=>{
            setTimeout(()=>{
                console.log("三秒后。");
                iter.next();
            },3000);
        }
        //使用生成器来依次那个调用上面函数的案例
        function * gen(){
            yield one();
            yield two();
            yield three();
        }
        let iter = gen();
        iter.next();
    </script>
</body>
</html>

案例二:next携带参数的异步

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script>
        let getUser = ()=>{
            setTimeout(()=>{
                let data = "用户数据";
                //调用next方法,并且将数据传入
                这里的data将作为第一个yield返回的结果
                iter.next(data);
            },1000);
        };

        let getOrders = ()=>{
            setTimeout(()=>{
                let data = "订单数据";
                //这里的data将作为第二个yield返回的结果
                iter.next(data)
            },1000);
        };

        let getGoods = ()=> {
            setTimeout(()=>{
                let data = "商品数据";
                //这里的data将作为第三个yield返回的结果
                iter.next(data);
            },1000);
        };

        function * gen(){
            let users = yield getUser();
            console.log(users);
            let orders = yield getOrders();
            console.log(orders);
            let goods = yield getGoods();
            console.log(goods);
        }

        let iter = gen();
        iter.next();
    </script>
</body>
</html>

以上是关于ES6 前端必学ES6,看完掌握新特性 的主要内容,如果未能解决你的问题,请参考以下文章

九个前端开发必学超级实用的 ES6 特性

九个前端开发必学超级实用的 ES6 特性

ES6新特性

前端入门21-JavaScript的ES6新特性

ES6必会重点汇总

前端面试经典题之ES6新特性