详解ES6-ES11必掌握的新特性


ES6-ES11
背景:ES是JS的一种标准规范,JS是它的实现,平时用的es5,es6后面拓展更多便捷语法,而es6具有里程碑意义,在框架源码中很多应用了es6。

ES6:
一、let变量声明以及声明特性、块级作用域

      1. 变量不能重复声明,会报错(区别var)
      let star = '罗志祥';
      let star = '小猪';

      2. 只生效于块儿级作用域:需要{ }  (es5的三种作用域:全局, 函数, eval(严格模式下))
      {
          let girl = '周扬青';
      } 

      3. 不存在变量提升(区别var)
      console.log(song); //报错
      let song = '恋爱达人';

      4. 不影响作用域链,即遵循自下而上寻找变量的规则。(注意)
      {
          let school = 'xxx';
          function fn(){
              console.log(school);
          }
          fn();// 'xxx'
      }

  案例:
        //获取div元素对象
        let items = document.getElementsByClassName('item');

        //遍历并绑定事件,如果用var声明i,点击事件触发时,i总会是3
        for(let i = 0;i<3;i++){
         //声明的变量相当于写在此位置
            items[i].onclick = function(){
                //修改当前元素的背景颜色
                // this.style.background = 'pink';  //回顾:this由执行该函数的对象决定,即元素节点,节点也是对象
                items[i].style.background = 'pink'; //函数作用域内会寻找i,没有便往上找;若用var声明i会找到全局的i
            }
        }
        
       在循环体中,var声明的变量挂载在全局,let则存在该作用域,前后不会相互影响
        {
          var i=0;
        }
        {
          var i=1;
        }...


二、const常量(一般常量使用大写(潜规则))

    1. 一定要赋初始值
    const A; //报错

    2. 常量的值不能修改
    
    3. const只存在于块儿级作用域
    {
        const PLAYER = 'UZI';
    }
    console.log(PLAYER);//报错

    4. 对于数组和对象的元素修改, 不算做对常量的修改, 不会报错,因为其引用地址不会改变
     const TEAM = ['UZI','MXLG','Ming','Letme'];
     TEAM.push('Meiko');


三、解构赋值(注意)

  ES6 允许按照一定模式从'数组和对象'中提取值,往'变量'进行赋值,

     1. 数组的解构
     const F4 = ['小沈阳','刘能','赵四','宋小宝'];
     let [xiao, liu, zhao, song] = F4;  //可理解成用于解构的四个变量

     console.log(xiao);//小沈阳
     console.log(liu);
     console.log(zhao);
     console.log(song);

     2. 对象的解构
     const zhao = {
         name: '赵本山',
         age: '不详',
         xiaopin: function(){
             console.log("我可以演小品");
         }
     };

     let {name, age, xiaopin} = zhao;   //可理解成用于解构的四个变量,只不过变量名和属性名一般一致
     console.log(name);
     console.log(age);
     console.log(xiaopin);

     也可以只将对象的一个属性拿到变量中:
     let {xiaopin} = zhao;
     xiaopin();


四、模板字符串

     ES6 引入新的声明字符串的方式 `` , 原es4用 '' "" 

        let str = `我也是一个字符串哦!`;
        console.log(str, typeof str); //string

        1. 内容中可以直接敲换行符,不用+连接,便于字符串里面出现html结构的场景
        let str = `<ul>
                    <li>沈腾</li>
                    <li>玛丽</li>
                    <li>魏翔</li>
                    <li>艾伦</li>
                    </ul>`;
        2. 变量拼接
        let lovest = '魏翔';
        let out = `${lovest}是我心目中最搞笑的演员!!`;
        console.log(out);

五、简化对象写法
   let name = 'xxx';
   let change = function(){
       console.log('我们可以改变你!!');
   }
   const school = { //属性名和变量/函数名一样时可简写
            name,
            change,
        }

六、箭头函数

  ES6 允许使用「箭头」(=>)定义函数。

    1. this 是静态的. this 始终指向函数声明时上一个作用域的 this ,即使用call等方法也不会改变.
      function getName(){
          console.log(this.name);
      }
      let getName2 = () => {
          console.log(this.name);
      }

      window.name = 'xxx';
      const school = {
          name: "ATGUIGU"
      }

      直接调用
      getName(); // 'xxx'
      getName2(); // 'xxx'
      
      call 方法调用
      getName.call(school); // 'ATGUIGU'
      getName2.call(school); // 'xxx'


    2. 不能作为构造实例化对象,会直接报错
        let Person = (name, age) => {
                    this.name = name;
                    this.age = age;
                }
                let me = new Person('xiao',30);
                console.log(me);//报错

    3. 没有 arguments 变量
        let fn = () => {
            console.log(arguments);
        }
        fn(1,2,3);//报错

    4. 箭头函数的简写
            1) 省略前面小括号, 当形参有且只有一个的时候
             let add = n => {
                 return n + n;
             }
             console.log(add(9));

            2) 省略花括号, 当代码体只有一条语句的时候, 又想其作为返回值,
            此时 return 可以省略,{}也要省略。
            语句的执行结果就是函数的返回值
            let pow = n => n * n;

    
七、函数参数默认值
    ES6 允许给函数参数赋值初始值

        1. 形参初始值 具有默认值的参数, 一般位置要靠后才有意义(潜规则)
         function add(a,b,c=10) {
             return a + b + c;
         }
         let result = add(1,2);

        2. 与解构赋值结合

        旧:function connect(option){
            console.log(option.host)
            console.log(option.username)
            ...
        }

        新:调用简洁、能设置默认值
        function connect({host="127.0.0.1", username,password, port}){
            console.log(host)
            console.log(username)
            ...
        }
        connect({
            host: 'atguigu.com',
            username: 'root',
            password: 'root',
            port: 3306
        })
            

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

    ES5 获取实参方式:
        function date(){
            console.log(arguments); //存放实参在伪数组中,属于对象
        }
        date('白芷','阿娇','思慧');
    拓展:如果是实参里面有数组,arguments会把数组当作一个元素

    ES6获取实参方式-rest 参数:
        function date(...args){
            console.log(args);存放实参在数组中
        }
        date('阿娇','柏芝','思慧');

        rest 参数必须要放到参数最后
        function fn(a,b,...args){
            console.log(a);//1
            console.log(b);//2
            console.log(args);//3,4,5,6
        }
        fn(1,2,3,4,5,6);


九、扩展运算符
    备注:只要...后是可迭代对象都就可以

    1.扩展运算符能将『数组』转换为逗号分隔的『参数序列』,即...数组,可拆分数组(记住)
        const tfboys = ['易烊千玺','王源','王俊凯'];

        function chunwan(){
            console.log(arguments);
        }
        chunwan(tfboys);    //chunwan(tfboys),arguments伪数组只有一个元素
        chunwan(...tfboys);     // chunwan('易烊千玺','王源','王俊凯'),arguments伪数组有三个元素

    2. 数组的合并
        const kuaizi = ['王太利','肖央'];
        const fenghuang = ['曾毅','玲花'];
        // const temp = kuaizi.concat(fenghuang);
        const temp = [...kuaizi, ...fenghuang];
        console.log(temp);

    3. 数组的克隆
     ( 其深浅拷贝与整体数组无关,与数组元素有关
        当数组里面没有引用类型时,为深拷贝;
        即当拷贝的内容只有一层时是深拷贝,层数很多时时浅拷贝)
        const sanzhihua = ['E','G','M'];
        const sanyecao = [...sanzhihua];//  ['E','G','M']
        console.log(sanyecao);

    4. 将伪数组转为真正的数组(特殊)
        const divs = document.querySelectorAll('div');
        const divArr = [...divs]; 
        console.log(divArr);


十、数据类型symbol

    1、Symbol函数创建:生成唯一的内置值,括号内的备注自定义
        let s = Symbol();
        console.log(s, typeof s);  //Symbol(),Symbol
        let s2 = Symbol('xxx');
        let s3 = Symbol('xxx');
        s2不等于s3,内置唯一值不同,备注相同

    2、Symbol.for 创建:括号里即为内置唯一值
        let s4 = Symbol.for('xxx');
        let s5 = Symbol.for('xxx');
        s4等于s5


    应用:
        向对象中添加方法 up down,而不影响里面可能存在的同名方法
        let game = {
            name:'俄罗斯方块',
            up: function(){},
            down: function(){}
        };
        
        game[Symbol('up')] = function(){  //Symbol()只要一写值就唯一
            console.log("我可以改变形状");
        }

        console.log(game);
        /*
        {
            name:'俄罗斯方块',
            up: function(){},
            down: function(){},
            Symbol('up'): ƒ ()
        }
        */

        或直接声明在内
        let youxi = {
            name:"狼人杀",
            [Symbol('say')]: function(){
                console.log("我可以发言")
            },
            [Symbol('zibao')]: function(){
                console.log('我可以自爆');
            }
        }

        console.log(youxi)
        /*
        {
            name:"狼人杀",
            Symbol('say'): ƒ ()
            Symbol('zibao'): ƒ ()
        }
        */


    Symbol内置属性:即Symbol.属性可作为对象的属性,能决定对应的方法执行时的情况,即自定义。如instanceof对应Symbol.hasInstance
        例1:
        class Person{
            static [Symbol.hasInstance](param){  //特殊
                console.log(param);  //param接收参数
                console.log("我被用来检测类型了");
                return false;  //收到决定返回值
            }
        }
        let o = {};
        console.log(o instanceof Person); //执行instanceof方法时,会执行hasInstance,相当于自定义了它

        例2:
        const arr = [1,2,3];
        const arr2 = [4,5,6];
        arr2[Symbol.isConcatSpreadable] = false;  //isConcatSpreadable对应concat,为false即连接后不展开:1,2,3,[4,5,6]
        console.log(arr.concat(arr2));


十一、迭代器

    任何数据结构只要部署 Iterator 接口,就可以 for...of 循环完成遍历操作、以及...拓展运算符
    原生具备 iterator 接口的数据(可用 for of 遍历)
        a) Array
        b) Arguments
        c) Set
        d) Map
        e) String
        f) TypedArray
        g) NodeList

    工作原理
    a) 创建一个指针对象,指向当前数据结构的起始位置
    b) 第一次调用对象的 next 方法,指针自动指向数据结构的第一个成员
    c) 接下来不断调用 next 方法,指针一直往后移动,直到指向最后一个成员
    d) 每调用 next 方法返回一个包含 value 和 done 属性的对象

    const xiyou = ['唐僧','孙悟空','猪八戒','沙僧'];

    //使用 for...of 遍历数组
        for(let v of xiyou){  
            console.log(v);  //唐僧,孙悟空,猪八戒,沙僧
        }

    注意:
        1.for...of与 for...in循环时的变量不同,for...in为key, for...of为value
        2.for...of要有迭代器才可以用

十二、生成器

  生成器其实就是一个特殊的函数,一种异步解决方案(也能解决回调地狱),内部原理类似迭代器
    //1.声明
    function * gen(){        
        console.log(111);
        yield '一只没有耳朵';   //yield为代码分割符,3个代码分隔符分割4块代码
        console.log(222);
        yield '一只没有尾部';
        console.log(333);
        yield '真奇怪';
        console.log(444);
    }

    //2.执行,获取迭代器对象:由next()方法控制,执行gen内部代码,到分隔符停止
    let iterator = gen();       
    console.log(iterator); //迭代器对象,具有next方法,调用next方法才能执行gen内部代码
    
    iterator.next();//111
    iterator.next();//222
    iterator.next();//333
    iterator.next();//444

    //next方法执行的返回值,value为yield值
    console.log(iterator.next());//{value:一只没有耳朵,done:false},执行第一个代码块,返回第一个yield值
    console.log(iterator.next());//{value:一只没有尾部,done:false}
    console.log(iterator.next());//{value:真奇怪,done:false}
    console.log(iterator.next());//{value:undefined,done:true},执行第四个代码块,只是没有返回值

    //遍历
     for(let v of iterator){
         console.log(v);   //四个{value:...,done:...}
     }


  生成器参数传递:

    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 iterator = gen('AAA'); (传入整个gen的参数)
    console.log(iterator.next()); //AAA;{value:111,done:false}
    console.log(iterator.next('BBB')); //BBB;{value:222,done:false} (next方法可以传入实参,传入后实参将为上一个yield的值)
    console.log(iterator.next('CCC')); //CCC;{value:333,done:false} 
    console.log(iterator.next('DDD')); //DDD;{value:undefined,done:false} 


  生成器函数解决回调地狱实例: 回调地狱即方法嵌套导致的代码不断缩进

  例子1:1秒执行第一个函数->2秒执行第二个函数->3秒执行第三个函数
    function one(){
        setTimeout(()=>{
            console.log(111);
            iterator.next();   //(iterator变量会一直往上面找)较特殊。即该代码一执行,自动执行下一个代码块
        },1000)
    }

    function two(){
        setTimeout(()=>{
            console.log(222);
            iterator.next();
        },2000)
    }
    ...

    function * gen(){
        yield one();  //因为在这里不需要返回值,只需要分割代码
        yield two();
        yield three();
    }

    //调用生成器函数
    let iterator = gen();  (let不影响作用域链,即遵循自下而上寻找变量的规则;写在此代码块位置相当于全局)
    iterator.next();


    例子1:  用户数据  订单数据  商品数据 (按顺序逐一执行,获取每个功能里的数据)
        function getUsers(){
            setTimeout(()=>{
                let data = '用户数据';
                //调用 next 方法, 并且将数据传入
                iterator.next(data);  (第二个next,作为第一个yield的值)
            }, 1000);
        }

        function getOrders(){
            setTimeout(()=>{
                let data = '订单数据';
                iterator.next(data);
            }, 1000)
        }

        function getGoods(){
            setTimeout(()=>{
                let data = '商品数据';
                iterator.next(data);
            }, 1000)
        }

        function * gen(){
            let users = yield getUsers();  //第一块代码执行完getUsers()后,users的值便可以直接拿
            let orders = yield getOrders();
            let goods = yield getGoods();
        }

        //调用生成器函数
        let iterator = gen();
        iterator.next();


十三、集合Set

    ES6 提供了新的数据结构 Set(集合)。它类似于数组,但成员的值都是唯一的,集合实现了
    iterator 接口,所以可以使用『扩展运算符』和『for…of…』进行遍历,集合的属性和方法:
 
    1) size 返回集合的元素个数
    2) add 增加一个新元素,返回当前集合
    3) delete 删除元素,返回 boolean 值
    4) has 检测集合中是否包含某个元素,返回 boolean 值
    5) clear 清空集合,返回 undefined


    //声明set
    let s = new Set();
    console.log(s,typeof s);  //Set(0){},Object
    let s2 = new Set(['大事儿','小事儿','好事儿','坏事儿','小事儿']);  (特殊)
    console.log(s2);  //Set(4){'大事儿','小事儿','好事儿','坏事儿'},自动去重

    //元素个数
     console.log(s2.size); //4
    //添加新的元素
     s2.add('喜事儿');
    //删除元素
     s2.delete('坏事儿');
    //检测
     console.log(s2.has('糟心事'));
    //清空
     s2.clear();
    //遍历
    for(let v of s2){
        console.log(v); //v为值
    }
        

  Set 实践例子:

    let arr = [1,2,3,4,5,4,3,2,1];

    1. 数组去重:先转换为集合,再转为数组
    let result = [...new Set(arr)];
    console.log(result);

    2. 交集:arr作为主操作数组必须先去重
    let arr2 = [4,5,6,5,6];
    let result = [...new Set(arr)].filter(item => {
        //实现arr元素在arr2中的判断即可;下面是采用s2作为集合使用has方法判断
        let s2 = new Set(arr2);// 4 5 6
        if(s2.has(item)){
            return true;
        }else{
            return false;
        }
    });
    简写:
    let result = [...new Set(arr)].filter(item => new Set(arr2).has(item));
    console.log(result);

    3. 并集
    let union = [...new Set([...arr, ...arr2])];
    console.log(union);

    4. 差集(交集取反)
    let diff = [...new Set(arr)].filter(item => !(new Set(arr2).has(item)));
    console.log(diff);

    补充:判断两个set是否相同:1.长度 2.元素是否包含.


十四、Map

    ES6 提供了 Map 数据结构。它类似于对象,[也是键值对的集合, 但是“键”
    的范围不限于字符串],各种类型的值(包括对象)都可以当作键。Map 也实现了
    iterator 接口,所以可以使用『扩展运算符』和『for…of…』进行遍历。

    Map 的属性和方法:
    1) size 返回 Map 的元素个数
    2) set 增加一个新元素,返回当前 Map(常用)
    3) get 返回键名对象的键值(常用)
    4) has 检测 Map 中是否包含某个元素,返回 boolean 值
    5) clear 清空集合,返回 undefined

        //声明 Map
        let m = new Map();

        m.set('name','xxx');
        m.set('change', function(){
            console.log("我们可以改变你!!");
        });

        console.log(m);
        /* 
            Map(2)
            0:{'name','xxx'} 
            1:{'change',function(){...}}
        */

        //size
        console.log(m.size);  //2  形式类似数组

        //删除
        m.delete('name');

        //获取
        console.log(m.get('change'));

        //清空
        m.clear();

        //遍历
        for(let v of m){
            console.log(v); //[键,值] (特殊)
        }


十五、class类

    ES6引入了 class 关键字,可以定义类。
    ES6的class只是一个语法糖,只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。

    ES5:
        function Phone(brand, price){
            this.brand = brand;
            this.price = price;
        }

        //添加方法
        Phone.prototype.call = function(){
            console.log("我可以打电话!!");
        }

        //实例化对象
        let Huawei = new Phone('华为', 5999);
        Huawei.call();

    ES6:关键词class、constructor
        class Shouji{
            //构造方法 名字不能修改
            constructor(brand, price){
                this.brand = brand;
                this.price = price;
            }

            //为了与其它语言对齐,方法必须使用该语法, 不能使用 ES5 的对象完整形式:call:function(){...} (特殊)
            call(){
                console.log("我可以打电话!!");
            }
        }

        let onePlus = new Shouji("1+", 1999);
        console.log(onePlus);


类的静态成员:关键词static
    函数对象(类)能调的方法与属性 --对应-- 写在构造函数funtion中/直接.添加的方法与属性   --对应--  静态成员
    实例对象(实例)能调的方法与属性 --对应-- 构造函数原型对象上的方法与属性
    
    function Phone(){
        }
        Phone.name = '手机';
        Phone.change = function(){
        }
        Phone.prototype.size = '5.5inch';

        let nokia = new Phone();
        console.log(nokia.name);//报错,该方法在函数对象上,不在实例对象
        nokia.change();//报错,该方法在函数对象上,不在实例对象
        console.log(nokia.size);//5.5inch

        class Phone{
            //静态属性,挂载在函数对象(类)上
            static name = '手机';
            static change(){
            },
            //公共属性,挂载在实例对象
            sex;
        }
        let nokia = new Phone();
        console.log(nokia.name);//报错
        console.log(Phone.name);//手机


类继承:

    原ES5:
          //手机
        function Phone(brand, price){
            this.brand = brand;
            this.price = price;
        }
        Phone.prototype.call = function(){
            console.log("我可以打电话");
        }

        //智能手机
        function SmartPhone(brand, price, color, size){
            Phone.call(this, brand, price);   //记住1,改变指向 传参
            this.color = color;
            this.size = size;
        }

        //记住2,设置子级构造函数的原型,相当于多一层父级原型
        SmartPhone.prototype = new Phone;
        SmartPhone.prototype.constructor = SmartPhone; //可选,做校正
      
        const chuizi = new SmartPhone('锤子',2499,'黑色','5.5inch');


    ES6:关键词extends、super

        class Phone{
            constructor(brand, price){
                this.brand = brand;
                this.price = price;
            }
            call(){
                console.log("我可以打电话!!");
            }
        }

        class SmartPhone extends Phone {
            //构造方法
            constructor(brand, price, color, size){
                super(brand, price);// 相当于ES5的Phone.call(this, brand, price)
                this.color = color;
                this.size = size;
            }

            photo(){
                console.log("拍照");
            }
            call(){       //重写父类方法
                console.log("我可以打电话!!");
            }
        }

        const xiaomi = new SmartPhone('小米',799,'黑色','4.7inch');
        xiaomi.call();
        xiaomi.photo();


类的get 和 set:(记)

      class Phone{
            get price(){
                console.log("价格属性被读取了");
                return 'iloveyou';  //返回处理后的内容
            }

            set price(newVal){
                console.log('价格属性被修改了');
                ...其它判断
            }
        }

        //实例化对象
        let s = new Phone();
        console.log(s.price);
        s.price = 'free';


十六、ES6的数值扩展:(列举部分)

    1. Number.EPSILON 是 JavaScript 表示的最小精度(小于该值认为两个数相等,利用此解决小数运算比较问题)
       EPSILON 属性的值接近于 2.2204460492503130808472633361816E-16
       
       function equal(a, b){
            if(Math.abs(a-b) < Number.EPSILON){
                return true;
            }else{
                return false;
            }
        }
        console.log(0.1 + 0.2 === 0.3);     //false
        console.log(equal(0.1 + 0.2, 0.3))  //true

    2.二进制和八进制    (记)
        let b = 0b1010;     //二进制,3
        let o = 0o777;      //八进制,511
        let x = 0xff;       //十六进制,255

    3.Number.isFinite  检测一个数值是否为有限数
        console.log(Number.isFinite(100));//true
        console.log(Number.isFinite(100/0));//false

      Number.isInteger 判断一个数是否为整数
        console.log(Number.isInteger(2.5));//false
        
    4. Number.isNaN 检测一个数值是否为 NaN  (记)
       console.log(Number.isNaN(123)); 
    (ES5中当成一个函数:isNaN(XX)  )

    5. Number.parseInt字符串转整数, Number.parseFloat字符串转浮点数(只是归类在Number上)
        console.log(Number.parseInt('5211314love'));
        console.log(Number.parseFloat('3.1415926神奇'));

    6. Math.trunc 将数字的小数部分抹掉 (记)
        console.log(Math.trunc(3.5));
        注意:与Math.floor(xx)不一样,在负数时有区别

    7. Math.sign 判断一个数到底为正数 负数 还是零   (记)
    console.log(Math.sign(100));//1
    console.log(Math.sign(0));//0
    console.log(Math.sign(-20000));//-1


十七、对象方法扩展

    1. Object.is 判断两个值是否完全相等 (类似===,但是又有区别),如果是引用型需地址相同
            console.log(Object.is(120, 120));   // true
            console.log(Object.is(NaN, NaN));   // true,特殊
            console.log(NaN === NaN);           // false,NaN不与任何相等

    2. Object.assign 对象的合并
            const config1 = {
                host: 'localhost',
            };
            const config2 = {
                port: 33060,
            }
            console.log(Object.assign(config1, config2));

    3. Object.setPrototypeOf (A,B) 为 A设置原型对象  Object.getPrototypeof
            const school = {
                name: 'xxx'
            }
            const cities = {
                xiaoqu: ['北京','上海','深圳']
            }
            Object.setPrototypeOf(school, cities);
            console.log(Object.getPrototypeOf(school));


十七、ES6 模块化语法

  模块功能主要由两个命令构成:export 和 import。
     
  a.export 命令用于规定模块的对外接口:

    1.分别暴露
        m1.js中:
        export let school = 'xxx';

        export function teach() {
            console.log("我们可以教给你开发技能");
        } 
    
    2.统一暴露  (暴露一个对象)
        let school = 'xxx';

        function findJob(){
            console.log("我们可以帮助你找工作!!");
        }

        export {school, findJob}; 

    3.默认暴露:关键字default
        export default {
            school: 'ATGUIGU',
            change: function(){
                console.log("我们可以改变你!!");
            }
        } 

   b.import 命令用于输入其他模块提供的功能:
        
      1. 通用的导入方式 (将js整个模块引入到变量m1)
        引入 m1.js 模块内容
        import * as m1 from "./src/js/m1.js";
       
      2. 解构赋值形式(适用分别暴露和统一暴露)
        import {school, teach} from "./src/js/m1.js";
        import {school as guigu, findJob} from "./src/js/m2.js"; (as声明别名,因为同一页面引入相同名称会报错)

      3. 简便形式,只针对默认暴露,
        import m3 from "./src/js/m3.js";
        

  项目中引入模块化的两个方式:(了解)
    
    1.html页面中的<script>标签中,使用import引入。

    2.先在html页面中<script src="./src/js/app.js" type="module"></script>引入入口文件,
    此时app.js文件里面统一import导入。(type="module",即将<script>标签的内容写到一个文件)


十八、ES7 新特性

     1.includes方法   ES5有:indexOf
     const mingzhu = ['西游记','红楼梦','三国演义','水浒传'];
     console.log(mingzhu.includes('西游记'));

     2.**幂运算
     console.log(2 ** 10);  //1024
     console.log(Math.pow(2, 10)); //也可使用幂运算

十九、ES8 新特性

优缺点:
async+await的优势在于处理then的调用链,使得promise代码更清晰,
并且也能解决回调地狱的问题。当然也存在一些缺点,如果多个异步代码没有依赖性(顺序要求)
却使用了await会导致性能上的降低。(await 调用起来时,它会阻塞后面的代码)


a.async 函数
    1. async 函数的返回值为 promise 对象,即将返回内容处理为promise 对象
    2. promise 对象的结果值由 async 后面函数执行的返回值决定

      async function fn(){ 
            1.返回一个字符串,不是抛出错误或返回一个 Promise ,则是成功状态
            // return 'xxx';
            2.抛出错误, 返回的结果是一个失败的 Promise
            // throw new Error('出错啦!');
            3.返回的结果如果是一个 Promise 对象,由该Promise 对象决定最后返回的Promise 对象。
            return new Promise((resolve, reject)=>{
                resolve('成功的数据');
                // reject("失败的错误");
            });
        }

        const result = fn();    (调用async 函数)
        result.then(value => {
            console.log(value);
        }, reason => {
            console.warn(reason);
        })

b.await 表达式
    1. await 必须写在 async 函数中
    2. await 右侧的表达式一般为 promise 对象
    3. await 返回的是 promise 成功的值
    4. await 的 promise 失败了, 就会抛出异常, 需要通过 try...catch 捕获处理

        // 发送 AJAX 请求, 返回的结果是 Promise 对象
        function sendAJAX(url) {
            return new Promise((resolve, reject) => {
                //1. 创建对象
                const x = new XMLHttpRequest();

                //2. 初始化
                x.open('GET', url);

                //3. 发送
                x.send();

                //4. 事件绑定
                x.onreadystatechange = function () {
                    if (x.readyState === 4) {
                        if (x.status >= 200 && x.status < 300) {
                            //成功,注意不能将return写在这里,因为这里返回的位置在function里。
                            resolve(x.response);
                        }else{
                            //失败
                            reject(x.status);
                        }
                    }
                }
            })
        }
    
        // async 与 await 测试  axios
        async function main(){
            let result = await sendAJAX("https://api.apiopen.top/getJoke");
            let tianqi = await sendAJAX('https://www.tianqiapi.com/api/?version=v1&city=%E5%8C%97%E4%BA%AC&appid=23941491&appsecret=TXoD5e8P')
            console.log(tianqi);
        }

        main();    //调用函数,顺序执行await;如果顺序执行后的结果需要返回处理,再接收即可。


ES8 对象方法拓展:

    (声明对象)
    const school = {
        name:"xxx",
        cities:['北京','上海','深圳'],
        xueke: ['前端','Java','大数据','运维']
    };

    1.获取对象所有的键
        console.log(Object.keys(school));
    2.获取对象所有的值
        console.log(Object.values(school));
    3.对象返回一个给定对象自身的 [key,value] 的数组, 返回结果为二维数组;
      用于将快速利用对象创建 Map (记)
       
        console.log(Object.entries(school));
        const m = new Map(Object.entries(school));
        console.log(m.get('cities')); //['北京','上海','深圳']

    4.对象属性的描述对象
        console.log(Object.getOwnPropertyDescriptors(school));
        能查到创建对象的详细信息:
        const obj = Object.create(null, {
            name: {
                value: 'xxx',
                writable: true,
                configurable: true,
                enumerable: true
            } 
        });

二十、ES9 新特性

    1.对象展开
        spread 扩展运算符与rest 参数与在 ES6 中已经引入,
        不过 ES6 中: spread 扩展运算符只针对于数组,rest 参数只针对函数传参
             ES9 中:spread 扩展运算符可以拆分对象
                    rest 参数可用于对象的解构赋值

        //对象解构赋值中的rest 参数
        function connect({host, port, ...user}){
            console.log(host);
            console.log(port);
            console.log(user); //{username: 'root',password: 'root',type: 'master'}
        }

        connect({
            host: '127.0.0.1',
            port: 3306,
            username: 'root',
            password: 'root',
            type: 'master'
        });


        //对象的spread 扩展运算符,可用于合并对象
        (...skillOne   =>  q: '天音波', w: '金钟罩' )
        const skillOne = {
            q: '天音波',
            w: '金钟罩' 
        }
        const skillTwo = {
            R: '大招'
        }

        const mangseng = {...skillOne, ...skillTwo};


    2.正则扩展-命名捕获分组

        let str = '<a href="http://www.atguigu.com">xxx</a>';

        要求:提取 url 与 『标签文本』
        const reg = /<a href="(.*)">(.*)<\/a>/;     (原写法)

        const result = reg.exec(str);
        console.log(result);    //exec方法执行后会有结果数组及其它属性
        console.log(result[0]); //<a href="http://www.atguigu.com">xxx</a>
        console.log(result[1]); //http://www.atguigu.com
        console.log(result[2]); //xxx
        
        //分组命名
        const reg = /<a href="(?<url>.*)">(?<text>.*)<\/a>/;     (新写法)
        const result = reg.exec(str);

        console.log(result.groups.url); //结果会多出与数组同级的属性groups,
        console.log(result.groups.text);


二十一、ES10 新特性

    1.Object.fromEntries 返回结果为对象
     将二维数组转换为对象,也可用于Map转对象。(Object.entries的逆运算)
        const result = Object.fromEntries([
            ['name','xxx'],
            ['xueke', 'Java,大数据,前端,云计算']
        ]);

        const m = new Map();
        m.set('name','ATGUIGU');
        const result = Object.fromEntries(m);

    2.trimStart 与 trimEnd

        let str = '   iloveyou   ';
        console.log(str.trimStart());  //iloveyou    
        console.log(str.trimEnd());    //   iloveyou

    3.flat 扁平数组:将多维数组转化为低位数组 ,参数为深度 是一个数字,默认为1  (记)
         const arr1 = [1,2,3,4,[5,6]];
         const arr2 = [1,2,3,4,[5,6,[7,8,9]]];
         console.log(arr1.flat());    //  [1,2,3,4,5,6]
         console.log(arr2.flat(2));   //[1,2,3,4,5,6,7,8,9]

    不确定维度时:arr.flat(Infinity);

    4.Symbol.prototype.description,获取Symbol描述
        let s = Symbol('xxx');
        console.log(s.description);  //xxx


二十二、ES11 新特性

    1.私有属性
     class Person{
            //公有属性,实例对象可以调用,区别静态属性
            name;
            //私有属性#,只能在类里面调用    (记)
            #age;
            #weight;
            constructor(name, age, weight){
                this.name = name;
                this.#age = age;   
                this.#weight = weight;
            }
            intro(){
                console.log(this.name);
                console.log(this.#age);(私有属性调用)
            }
        }

        const girl = new Person('晓红', 18, '45kg');
        console.log(girl.name);//晓红
        console.log(girl.#age);//报错

        girl.intro();//晓红,18

    2.Promise.allSettled (记)
      接收一个promise数组,返回一个promise,状态成功,值为每一个promise的状态和值组成的数组

        const p1 = new Promise((resolve, reject)=>{
            setTimeout(()=>{
                resolve('商品数据 - 1');
            },1000)
        });

        const p2 = new Promise((resolve, reject)=>{
            setTimeout(()=>{
                resolve('商品数据 - 2');
                // reject('出错啦!');
            },1000)
        });

         const result = Promise.allSettled([p1, p2]);
         const res = Promise.all([p1, p2]); 
         console.log(res);
         //promiseStatus: resolved , promiseValue: Array(2) 里面为{status:..,value:..}  

         const res = Promise.all([p1, p2]);
         //Promise.all也接收一个promise数组,返回一个promise,
         状态全部成功才成功,值为所有成功promise的值组成的数组;
         有一个失败则为失败,值为失败promise的值。
         
    3.可选链操作符?.  (记)
      避免某些值没传,防止对null 或者 undefined进行属性调用时的报错,如果给定的访问过程中有内容不存在,则返回 undefined
     function main(config){        
            // const dbHost = config.db.host;
            const dbHost = config?.db?.host;    
            //此时若没有整个config/db属性,即访问过程不成功也不会报错,而是输出undefined
            console.log(dbHost);
        }

        main({
            db: {
                host:'192.168.1.100',
                username: 'root'
            }        
        })

    4.动态 import  (记)
     import * as m1 from "./hello.js";  //静态引入,无论是否调用都会引入页面
     
     const btn = document.getElementById('btn');
     btn.onclick = function(){
        import('./hello.js').then(module => {   //动态引入,通过import()函数,其返回的是一个promise
            module.hello();     (如果执行,则引入模块)
        });
     }

    5.BigInt

    //大整形表示形式
    let n = 521n;
    console.log(n, typeof(n)); //521n,BigInt

    //函数,只能将整数转为大整数
    let n = 123;
    console.log(BigInt(n)); 
    console.log(BigInt(1.2)); //报错
  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值