系列学习前端之第 5 章:学习 ES6 ~ ES11

1、什么是 ECMAScript

ECMAScript 是由 Ecma 国际通过 ECMA-262 标准化的脚本程序设计语言。

从第 6 版开始,发生了里程碑的改动,并保持着每年迭代一个版本的习惯。

ES6=2015年,ES7=2016年,ES8=2017年,ES9=2018年,ES10=2019年,ES11=2020年以此类推。

1.1 为什么要学习****ES6

⚫ ES6 的版本变动内容最多,具有里程碑意义
⚫ ES6 加入许多新的语法特性,编程实现更简单、高效
⚫ ES6 是前端发展趋势,就业必备技能

2、ECMASript 6****新特性

2.1.let****关键字

let 关键字用来声明变量,使用 let 声明的变量有几个特点:

  1. 不允许重复声明
  2. 块儿级作用域
  3. 不存在变量提升
  4. 不影响作用域链
    应用场景:以后声明变量使用 let 就对了
javascript 复制代码
    <script>
        //声明变量
        let a;
        let b, c, d;
        let e = 100;
        let f = 521, g = 'iloveyou', h = [];

        //1. 变量不能重复声明
        //let star = '罗志祥';
        //let star = '小猪';
        //console.log("Uncaught SyntaxError: Identifier 'star' has already been declared");

        //2. 块儿级作用域  全局, 函数, eval
        //类似块级作用于的还有:if else while for 
        {
            let girl = '周扬青';
            console.log(girl);//可以正确输出
        }
        //console.log(girl);
        //console.log("Uncaught ReferenceError: girl is not defined at");

        //3. 不存在变量提升
        // console.log(song);
        // let song = '爱唱歌';
        // console.log("Uncaught ReferenceError: Cannot access 'song' before initialization");

        //4. 不影响作用域链
        {
            let school = '清华大学';
            function fn() {
                console.log(school);
            }
            fn();
        }
    </script>

2.2. const****关键字

const 关键字用来声明常量, const 声明有以下特点:

  1. 声明必须赋初始值
  2. 标识符一般为大写
  3. 不允许重复声明
  4. 值不允许修改
  5. 块儿级作用域
    注意 : 对象属性修改和数组元素变化不会出发 const 错误
    应用场景:声明对象类型使用 const ,非对象类型声明选择 let
javascript 复制代码
    <script>
        //声明常量
        const SCHOOL = '清华大学';

        //1. 一定要赋初始值
        //const A;
        //console.log("Uncaught SyntaxError: Missing initializer in const declaration");

        //2. 一般常量使用大写(潜规则)
        const a = 100;
        //3. 常量的值不能修改
        //SCHOOL = '北京大学';
        //console.log("Uncaught TypeError: Assignment to constant variable");

        //4. 块儿级作用域
        // {
        //     const PLAYER = '乔丹';
        // }
        // console.log(PLAYER);
        // console.log("Uncaught ReferenceError: PLAYER is not defined at");

        //5. 对于数组和对象的元素修改, 不算做对常量的修改, 不会报错
        const BAT = ['百度', '阿里巴巴', '腾讯'];
        BAT.push('字节跳动');
        console.log(BAT);//输出:['百度', '阿里巴巴', '腾讯', '字节跳动']

    </script>

**2.3.**变量的解构赋值

ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构赋值。

javascript 复制代码
    <script>
        //ES6 允许按照一定模式从数组和对象中提取值,对变量进行赋值,这被称为解构赋值。
        //1. 数组的结构
        const SCHOOL = ['清华大学', '北京大学'];
        let [qinghua, beida] = SCHOOL;
        console.log(qinghua);//输出清华大学
        console.log(beida);//输出北京大学

        //2. 对象的解构
        const student = {
            name: "小明",
            age: 18,
            like: function () {
                console.log("我喜欢打篮球");
            }
        }
        let { name, age, like } = student;
        console.log(name);//输出小明
        console.log(age);//输出18
        console.log(like);//输出:ƒ () {console.log("我喜欢打篮球");}
        like();//输出:我喜欢打篮球
    </script>

注意:频繁使用对象方法、数组元素,就可以使用解构赋值形式

**2.4.**模板字符串

模板字符串( template string )是增强版的字符串,用反引号(` )标识,特点:

  1. 字符串中可以出现换行符
  2. 可以使用 ${xxx} 形式输出变量
javascript 复制代码
    <script>
        // ES6 引入新的声明字符串的方式 『``』 
        //1. 声明
        let str = `这是一个字符串`;
        console.log(str, typeof str);//输出:这是一个字符串 string

        //2. 内容中可以直接出现换行符
        let SCHOOL = `<ul>
            <li>清华大学</li>
            <li>北京大学</li>
            </ul>`;

        //3.变量拼接
        let boy = `马云`;
        let word = `${boy}说让天下没有难做的生意!`;
        console.log(word);//输出:马云说让天下没有难做的生意!
    </script>

注意:当遇到字符串与变量拼接的情况使用模板字符串

**2.5.**简化对象写法

ES6 允许在大括号里面,直接写入变量和函数,作为对象的属性和方法。这样的书写更加简洁。

javascript 复制代码
    <script>
        //ES6 允许在大括号里面,直接写入变量和函数,作为对象的属性和方法。
        //这样的书写更加简洁
        let name = '马云';
        let word = function () {
            console.log('让天下没有难做的生意');
        }

        const obj = {
            name,
            word,
            say() {
                console.log("幸福是奋斗出来的!");
            }
        }
        console.log(name);//输出:马云
        console.log(word);//输出:ƒ () { console.log('让天下没有难做的生意'); }
        console.log(obj);//输出:{name: '马云', word: ƒ, say: ƒ}
    </script>

注意:对象简写形式简化了代码,所以以后用简写就对了

**2.6.**箭头函数

ES6 允许使用「箭头」( => )定义函数。
箭头函数的注意点 :

  1. 如果形参只有一个,则小括号可以省略
  2. 函数体如果只有一条语句,则花括号可以省略,函数的返回值为该条语句的执行结果
  3. 箭头函数 this 指向声明时所在作用域下 this 的值
  4. 箭头函数不能作为构造函数实例化
  5. 不能使用 arguments
javascript 复制代码
    <script>
        // ES6 允许使用「箭头」(=>)定义函数。
        //声明一个函数
        let fn = (a, b) => {
            return a + b;
        }
        //调用函数
        let result = fn(3, 5);
        console.log(result);//输出:8


        //1. this 是静态的. this 始终指向函数声明时所在作用域下的 this 的值
        function getName() {
            console.log(this.name);
        }
        let getName2 = () => {
            console.log(this.name);
        }

        //设置 window 对象的 name 属性
        window.name = '清华大学';
        const school = {
            name: "北京大学"
        }

        //直接调用
        getName();//输出:清华大学(作用域是 window)
        getName2();//输出:清华大学(作用域是 window)

        //call 方法调用
        getName.call(school);//输出:北京大学
        getName2.call(school);//输出:清华大学(作用域是 window)

        //2. 不能作为构造实例化对象
        // let Person = (name, age) => {
        //     this.name = name;
        //     this.age = age;
        // }
        // let me = new Person('张三', 18);
        // console.log(me);//输出错误信息:Person is not a constructor at

        //3. 不能使用 arguments 变量
        // let fn = () => {
        //     console.log(arguments);
        // }
        // fn(1, 2, 3);//输出错误信息:Uncaught SyntaxError: Identifier 'fn' has already been declared

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

        //2) 省略花括号, 当代码体只有一条语句的时候, 此时 return 必须省略
        // 而且语句的执行结果就是函数的返回值
        let pow = n => n * n;

        console.log(pow(9));//输出:81

    </script>

注意:箭头函数不会更改this指向,用来指定回调函数会非常合适
箭头函数适合与 this 无关的回调,比如:定时器、数组的方法回调
箭头函数不适合与 this 有关的回调有:事件回调、对象的方法

2.7. rest****参数

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

javascript 复制代码
<body>
    <div>我是div1</div>
    <div>我是div2</div>
    <div>我是div3</div>
    <script>
        // ES6 引入 rest 参数,用于获取函数的实参,用来代替 arguments
        // rest 参数
        function getUserName(...args) {
            console.log(args);
        }
        getUserName('刘亦菲', '关之琳', '刘雯雯');//输出:['刘亦菲', '关之琳', '刘雯雯']

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

        //1. 数组的合并
        const university = ["清华大学", "北京大学"];
        const foreign = ["哈佛大学", "牛津大学"];
        const concat1 = university.concat(foreign);
        console.log("concat1=" + concat1);//输出:concat1=清华大学,北京大学,哈佛大学,牛津大学
        const concat2 = [...university, ...foreign];
        console.log("concat2=" + concat2);//输出:concat2=清华大学,北京大学,哈佛大学,牛津大学

        //2. 数组的克隆
        const student = ["小明", "小花", "小聪"];
        const copy1 = [...student];
        console.log("copy1=" + copy1);//输出:copy1=小明,小花,小聪

        //3. 将伪数组转为真正的数组
        const divs = document.querySelectorAll('div');//注意在文档顶部有3个div
        const divArr = [...divs];
        console.log(divArr);//输出:[div, div, div]

    </script>

</body>

注意: rest 参数适合不定个数参数函数的场景

2.8. spread****扩展运算符

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

javascript 复制代码
    <script>
        // 『...』 扩展运算符能将『数组』转换为逗号分隔的『参数序列』
        //声明一个数组 ...
        const F4 = ['刘德华', '黎明', '张学友', '郭富城'];

        // 声明一个函数
        function tianwang() {
            console.log(arguments);
        }
        tianwang(...F4);
        //输出:Arguments(4) ['刘德华', '黎明', '张学友', '郭富城', callee: ƒ, Symbol(Symbol.iterator): ƒ]

    </script>

2.9.Symbol

ES6 引入了一种新的原始数据类型 Symbol,表示独一无二的值。它是JavaScript 语言的第七种数据类型,是一种类似于字符串的数据类型。
Symbol 特点

  1. Symbol 的值是唯一的,用来解决命名冲突的问题
  2. Symbol 值不能与其他数据进行运算
  3. Symbol 定义 的 对象属 性 不能 使 用 for...in 循 环遍 历 ,但 是可 以 使 用 Reflect.ownKeys 来获取对象的所有键名。
javascript 复制代码
    <script>
        //创建 symbol
        let s1 = Symbol();
        console.log(s1, typeof s1);//输出:Symbol() 'symbol'

        let s2 = Symbol("清华大学");
        let s3 = Symbol.for("广东省深圳市");

        //不能与其他数据进行运算
        //let result1 = s1 + 100;
        //console.log(result1);//输出:Uncaught TypeError: Cannot convert a Symbol value to a number
        //let result2 = s2 + "教授";
        //console.log(result2);//输出:Uncaught TypeError: Cannot convert a Symbol value to a string

        let youxi = {
            name: "王者荣耀",
            [Symbol('zhongdan')]: function () {
                console.log("我可以中单")
            },
            [Symbol('daye')]: function () {
                console.log('我可以打野');
            }
        }
        console.log(youxi)
    </script>

: 遇到唯一性的场景时要想到 Symbol

**2.10.**迭代器

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

  1. ES6 创造了一种新的遍历命令 for...of 循环, Iterator 接口主要供 for...of 消费
  2. 原生具备 iterator 接口的数据 ( 可用 for of 遍历 )
    a) Array
    b) Arguments
    c) Set
    d) Map
    e) String
    f) TypedArray
    g) NodeList
  3. 工作原理
    a) 创建一个指针对象,指向当前数据结构的起始位置
    b) 第一次调用对象的 next 方法,指针自动指向数据结构的第一个成员
    c) 接下来不断调用 next 方法,指针一直往后移动,直到指向最后一个成员
    d) 每调用 next 方法返回一个包含 value 和 done 属性的对象
    : 需要自定义遍历数据的时候,要想到迭代器。
javascript 复制代码
    <script>
        let F4 = ["刘德华", "郭富城", "黎明", "张学友"];
        //使用 for...of 遍历数组
        for (let v of F4) {
            console.log(v);//循环输出:刘德华、郭富城、黎明、张学友
        }

        let iterator = F4[Symbol.iterator]();
        //调用对象的next方法
        console.log(iterator.next());//输出:{value: '刘德华', done: false}
        console.log(iterator.next());//输出:{value: '郭富城', done: false}
        console.log(iterator.next());//输出:{value: '黎明', done: false}
        console.log(iterator.next());//输出:{value: '张学友', done: false}
        console.log(iterator.next());//输出:{value: undefined, done: true}

        //自定义遍历数据
        const NBA = {
            name: "美国篮球协会",
            player: ["乔丹", "麦迪", "姚明"],
            [Symbol.iterator]() {
                //索引变量
                let index = 0;
                let _this = this;
                return {
                    next: function () {
                        if (index < _this.player.length) {
                            const result = {
                                value: _this.player[index], done: false
                            };
                            //下标自增
                            index++;
                            return result;
                        } else {
                            return { value: undefined, done: true };
                        }
                    }
                };
            }
        }

        //遍历这个 NBA 对象
        for (let v of NBA) {
            console.log(v);//输出:乔丹、麦迪、姚明
        }


    </script>

**2.11.**生成器

生成器函数是 ES6 提供的一种异步编程解决方案,语法行为与传统函数完全不同。生成器其实就是一个特殊的函数。

javascript 复制代码
    <script>
        //生成器其实就是一个特殊的函数
        //异步编程  纯回调函数
        //函数代码的分隔符
        function* NBA() {
            yield "乔丹";
            yield "麦迪";
            yield "姚明";
        }


        let iterator = NBA();
        console.log(iterator.next());//输出:{value: '乔丹', done: false}
        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 NBA()) {
            console.log(v);//输出:乔丹、麦迪、姚明
        }

        //生成器函数参数
        function* university(arg) {
            console.log("arg=" + arg);
            let one = yield "清华大学";
            console.log("one=" + one);

            let two = yield "北京大学";
            console.log("two=" + two);

            let three = yield "哈佛大学";
            console.log("three=" + three);
        }

        //执行获取迭代器对象
        let iter = university("上海交大");
        console.log("iter.next1=" + iter.next());
        //next方法可以传入实参
        console.log("iter.next2=" + iter.next("医科大"));
        console.log("iter.next3=" + iter.next("中山大学"));
        console.log("iter.next4=" + iter.next("复旦大学"));

        //依次输出:
        /*
        arg=上海交大
        iter.next1=[object Object]
        one=医科大
        iter.next2=[object Object]
        two=中山大学
        iter.next3=[object Object]
        three=复旦大学
        iter.next4=[object Object]
        */


        //生成器函数实例
        //异步编程、文件操作、网络操作(ajax、Request、数据库操作)
        //模拟获取:用户数据、订单数据、商品数据
        function getUserInfo() {
            setTimeout(
                () => {
                    let data = "用户数据";
                    console.log(data);
                    //调用 next 方法,并且将数据传入
                    info.next(data);
                }, 1000)
        }

        function getOrderInfo() {
            setTimeout(
                () => {
                    let data = "订单数据";
                    console.log(data);
                    info.next(data);
                }, 1000)
        }

        function getGoodsInfo() {
            setTimeout(
                () => {
                    let data = "商品数据";
                    console.log(data);
                    info.next(data);
                }, 1000)
        }

        function* getMallInfo() {
            yield getUserInfo();
            yield getOrderInfo();
            yield getGoodsInfo();
        }

        //调用生成器函数
        let info = getMallInfo();
        info.next();//依次输出:用户数据、订单数据、商品数据

    </script>

代码说明:

  1. * 的位置没有限制
  2. 生成器函数返回的结果是迭代器对象,调用迭代器对象的 next 方法可以得到 yield 语句后的值
  3. yield 相当于函数的暂停标记,也可以认为是函数的分隔符,每调用一次 next 方法,执行一段代码
  4. next 方法可以传递实参,作为 yield 语句的返回值

2.12. Promise(重点掌握)

Promise 是 ES6 引入的异步编程的新解决方案。语法上 Promise 是一个构造函数,用来封装异步操作并可以获取其成功或失败的结果。

  1. Promise 构造函数 : Promise (excutor) {}
  2. Promise.prototype.then 方法
  3. Promise.prototype.catch 方法
2.12.1 Promise基本语法
javascript 复制代码
    <script>
        // promise 基本语法
        //实例化 Promise 对象
        const promise = new Promise(function (resolve, reject) {
            /* 正常读取数据*/
            setTimeout(function () {
                let data = '数据库中的用户数据';
                resolve(data);
            }, 1000);


            /*
            setTimeout(function () {
                let err = '数据读取失败';
                reject(err);
            });
            */
        });

        //调用 promise 对象的 then 方法
        promise.then(function (value) {
            console.log(value);
        }, function (reason) {
            console.error(reason);
        })

    </script>
2.12.2 Promise封装AJAX
javascript 复制代码
    <script>
        const p = new Promise((resolve, reject) => {
            //1. 创建对象
            const xhr = new XMLHttpRequest();

            //2. 初始化
            xhr.open("GET", "输入具体的 URL 地址,比如 http://www.baidu.com/");

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

            //4. 绑定事件, 处理响应结果
            xhr.onreadystatechange = function () {
                //判断
                if (xhr.readyState === 4) {
                    //判断响应状态码 200-299
                    if (xhr.status >= 200 && xhr.status < 300) {
                        //表示成功
                        resolve(xhr.response);
                    } else {
                        //如果失败
                        reject(xhr.status);
                    }
                }
            }
        })

        //指定回调
        p.then(function (value) {
            console.log(value);
        }, function (reason) {
            console.error(reason);
        });
    </script>
2.12.3 Promise then方法
javascript 复制代码
   <script>
        //创建 promise 对象
        const p2 = new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve('用户数据');
                // reject('出错啦');
            }, 1000)
        });

        //调用 then 方法  then方法的返回结果是 Promise 对象, 对象状态由回调函数的执行结果决定
        //1. 如果回调函数中返回的结果是 非 promise 类型的属性, 状态为成功, 返回值为对象的成功的值

        // const result = p2.then(value => {
        //     console.log(value);
        //     //1. 非 promise 类型的属性
        //     // return 'iloveyou';
        //     //2. 是 promise 对象
        //     // return new Promise((resolve, reject)=>{
        //     //     // resolve('ok');
        //     //     reject('error');
        //     // });
        //     //3. 抛出错误
        //     // throw new Error('出错啦!');
        //     throw '出错啦!';
        // }, reason=>{
        //     console.warn(reason);
        // });

        //链式调用
        p2.then(value => {

        }).then(value => {

        });

    </script>
2.12.3 Promise catch方法
javascript 复制代码
    <script>
        const p3 = new Promise((resolve, reject) => {
            setTimeout(() => {
                //设置 p 对象的状态为失败, 并设置失败的值
                reject("出错啦!");
            }, 1000)
        });

        // p3.then(function(value){}, function(reason){
        //     console.error(reason);
        // });

        p3.catch(function (reason) {
            console.warn(reason);
        });
    </script>

2.13. Set

ES6 提供了新的数据结构 Set(集合)。它类似于数组,但成员的值都是唯一的,集合实现了 iterator 接口,所以可以使用『扩展运算符』和『 for...of...』进行遍历,集合的属性和方法:

  1. size 返回集合的元素个数
  2. add 增加一个新元素,返回当前集合
  3. delete 删除元素,返回 boolean 值
  4. has 检测集合中是否包含某个元素,返回 boolean 值
  5. clear 清空集合,返回 undefined
javascript 复制代码
    <script>
        //创建一个空集合
        let emptySet = new Set();

        //创建一个非空集合
        let wangzhe = new Set(["射手", "法师", "打野", "上单", "辅助"]);
        //返回集合的元素个数
        console.log(wangzhe.size);//输出:5
        //遍历集合
        for (let v of wangzhe) {
            console.log(v);//输出:射手、法师、打野、上单、辅助
        }
        //添加新元素
        console.log(wangzhe.add("野怪"));//输出:Set(6) {'射手', '法师', '打野', '上单', '辅助', '野怪'}
        //删除元素
        console.log(wangzhe.delete("野怪"));//输出:true
        //检测是否存在某个值
        console.log(wangzhe.has("野怪"));//输出:false
        //清空集合
        console.log(wangzhe.clear());//输出:undefined

        //set 集合的去重、并、交、差集合
        let arr1 = ["北京", "上海", "广州", "深圳", "上海"];
        //数组去重
        let repeat = [...new Set(arr1)];
        console.log("repeat=" + repeat);//输出:repeat=北京,上海,广州,深圳

        //交集
        let arr2 = ["广州", "深圳", "武汉"];
        let intersection = [...new Set(arr1)].filter(item => new Set(arr2).has(item));
        console.log("intersection=" + intersection);//输出:intersection=广州,深圳

        //并集
        let union = [...new Set([...arr1, ...arr2])];
        console.log("union=" + union);//输出:union=北京,上海,广州,深圳,武汉

        //差集
        let diff = [...new Set(arr1)].filter(item => !(new Set(arr2).has(item)));
        console.log("diff=" + diff);//输出:diff=北京,上海

    </script>

2.14. Map

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

  1. size 返回 Map 的元素个数
  2. set 增加一个新元素,返回当前 Map
  3. get 返回键名对象的键值
  4. has 检测 Map 中是否包含某个元素,返回 boolean 值
  5. clear 清空集合,返回 undefined
javascript 复制代码
    <script>
        //声明一个 map
        let map = new Map();
        //添加元素
        map.set("name", "马云");
        map.set("word", function () {
            console.log("让天下没有难做的生意!");
        });

        let school = {
            name: "浙江师范大学"
        };
        map.set(school, ["北京大学", "清华大学"]);

        //map集合数据长度
        console.log("map.size=" + map.size);//输出:map.size=3
        //删除
        console.log(map.delete("name"));//输出:true
        //获取map数据
        console.log("word=" + map.get("word"));//输出:word=function () {console.log("让天下没有难做的生意!");}
        console.log("school=" + map.get("school"));//输出:school=undefined

        //遍历
        for (let m of map) {
            console.log(m);
        }
        /*
        输出:
        ['word', ƒ]
        [{...}, Array(2)]
        */

        //清空 map
        console.log(map.clear());//输出:undefined
    </script>

2.15. class****类

ES6 提供了更接近传统语言的写法,引入了 Class(类)这个概念,作为对象的模板。通过 class 关键字,可以定义类。基本上, ES6 的 class 可以看作只是一个语法糖,它的绝大部分功能, ES5 都可以做到,新的 class 写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。
知识点:

  1. class 声明类
  2. constructor 定义构造函数初始化
  3. extends 继承父类
  4. super 调用父级构造方法
  5. static 定义静态方法和属性
  6. 父类方法可以重写
javascript 复制代码
    <script>
        class Phone {
            //构造方法
            constructor(brand, price) {
                this.brand = brand;
                this.price = price;
            }
            //方法必须使用该语法,不能使用 ES5 的对象完整形式
            call() {
                console.log("我是一部手机");
            }
        }

        let Huawei = new Phone("华为折叠手机", 8999);
        console.log(Huawei);//输出:Phone {brand: '华为折叠手机', price: 8999}

        //class 的 get、set
        class Game {
            get name() {
                console.log("游戏的名字属性被读取了");
                return "王者荣耀";
            }

            set name(newName) {
                console.log("游戏的名字属性被修改了");
            }
        }

        //实例化对象
        let play = new Game();
        console.log(play.name);//输出:游戏的名字属性被读取了、 王者荣耀
        play.name = "打野";//游戏的名字属性被修改了

        //类的静态成员
        class University {
            static name = "清华大学";
            static word() {
                console.log("自强不息,厚德载物");
            }
            student() {
                console.log("好好学习,天天向上");
            }
        }
        let Tom = new University();
        console.log("Tom.name=" + Tom.name);//输出:Tom.name=undefined
        console.log("Tom.word=" + Tom.word);//输出:Tom.word=undefined
        console.log("Tom.student=" + Tom.student);//输出:Tom.student=student() {console.log("好好学习,天天向上");}
        console.log("University.name=" + University.name);//输出:University.name=清华大学
        console.log("University.word=" + University.word);//输出:University.word=word() {console.log("自强不息,厚德载物");}
        //结论:类的静态成员只能被该类访问

        //类的继承
        class Person {
            constructor(age, sex) {
                this.age = age;
                this.sex = sex;
            }
            //父类的成员属性
            call() {
                console.log("我的人类共有的特征");
            }
        }

        //子类继承
        class OtherPeople extends Person {
            constructor(age, sex, name) {
                super(age, sex);
                this.name = name;
            }
            //唱歌
            sing() {
                console.log("我会唱歌");
            }
            codding() {
                console.log("我会编程");
            }
        }
        const XiaoMing = new OtherPeople(18, "男", "我叫小明");
        XiaoMing.call();//输出:我的人类共有的特征
        XiaoMing.sing();//输出:我会唱歌
        XiaoMing.codding();//输出:我会编程

    </script>

**2.16.**数值扩展

**2.16.1.**二进制和八进制

ES6 提供了二进制和八进制数值的新的写法,分别用前缀 0b 和 0o 表示。

2.16.2. Number.isFinite()Number.isNaN()

Number.isFinite() 用来检查一个数值是否为有限的
Number.isNaN() 用来检查一个值是否为 NaN

2.16.3. Number.parseInt()Number.parseFloat()

ES6 将全局方法 parseInt 和 parseFloat ,移植到 Number 对象上面,使用不变。

2.16.4. Math.trunc

用于去除一个数的小数部分,返回整数部分。

2.16.5. Number.isInteger

Number.isInteger() 用来判断一个数值是否为整数

javascript 复制代码
    <script>
        //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(1 + 2 == 3);//输出:true
        console.log(1 + 2 === 3);//输出:true
        console.log(0.1 + 0.2 == 0.3);//输出:false
        console.log(0.1 + 0.2 === 0.3);//输出:false
        console.log(equal(0.1 + 0.2, 0.3));//输出:false

        //2、Number.isFinite 检测一个数值是否为有限数
        console.log("-------------------------------------");
        console.log(Number.isFinite(100));//输出:true
        console.log(Number.isFinite(100 / 0));//输出:false
        console.log(Number.isFinite(Infinity));//输出:false

        //3. Number.isNaN 检测一个数值是否为 NaN
        console.log("-------------------------------------");
        console.log(Number.isNaN(123));//输出:false
        console.log(Number.isNaN(NaN));//输出:true

        //4. Number.parseInt Number.parseFloat字符串转整数
        console.log("-------------------------------------");
        console.log(Number.parseInt('123砍三刀'));//输出:123
        console.log(Number.parseFloat('3.1415926圆周率'));//输出:3.1415926

        //5. Number.isInteger 判断一个数是否为整数
        console.log("-------------------------------------");
        console.log(Number.isInteger(666));//输出:true
        console.log(Number.isInteger(8.88));//输出:false
        console.log(Number.isInteger("一刀999"));//输出:false

        //6. Math.trunc 将数字的小数部分抹掉
        console.log("-------------------------------------");
        console.log(Math.trunc(1.25));//输出:1

        //7. Math.sign 判断一个数到底为正数 负数 还是零
        console.log("-------------------------------------");
        console.log(Math.sign(0));//输出:0
        console.log(Math.sign(12306));//输出:1
        console.log(Math.sign(-2.98));//输出:-1

    </script>

**2.17.**对象扩展

ES6 新增了一些 Object 对象的方法

  1. Object.is 比较两个值是否严格相等,与『 === 』行为基本一致( +0 与 NaN )
  2. Object.assign 对象的合并,将源对象的所有可枚举属性,复制到目标对象
  3. proto 、 setPrototypeOf 、 setPrototypeOf 可以直接设置对象的原型
javascript 复制代码
    <script>
        //1. Object.is 判断两个值是否完全相等 
        console.log(Object.is(666, 666));//输出:true
        console.log(Object.is(NaN, NaN));//输出:true
        console.log(NaN === NaN);//输出:false

        //2. Object.assign 对象的合并
        const dbConfigDev = {
            host: 'http://127.0.0.1',
            port: 3306,
            name: 'dev',
            pass: 'dev',
            dbName: 'dev数据库',
            remark: "这是备注,开发环境数据库"
        };
        const dbConfigTest = {
            host: 'http://127.0.0.2',
            port: 8848,
            name: 'test',
            pass: 'test',
            dbName: 'test数据库',
            info: "请开启防火墙"
        }
        console.log(Object.assign(dbConfigDev, dbConfigTest));
        //输出:{host: 'http://127.0.0.2', port: 8848, name: 'test', pass: 'test', dbName: 'test数据库', info: "请开启防火墙",remark: "这是备注,开发环境数据库"}

        //3. Object.setPrototypeOf 设置原型对象  Object.getPrototypeof
        const school = {
            name: '清华大学'
        }
        const cities = {
            xiaoqu: ['北京', '上海', '深圳']
        }
        Object.setPrototypeOf(school, cities);
        console.log(Object.getPrototypeOf(school));//输出:{xiaoqu: Array(3)}['北京', '上海', '深圳']
        console.log(school);//输出:{name: '清华大学'}

    </script>

**2.18.**模块化

模块化是指将一个大的程序文件,拆分成许多小的文件,然后将小文件组合起来。

**2.18.1.**模块化的好处

模块化的优势有以下几点:

  1. 防止命名冲突
  2. 代码复用
  3. 高维护性
**2.18.2.**模块化规范产品

ES6 之前的模块化规范有:

  1. CommonJS => NodeJS 、 Browserify
  2. AMD => requireJS
  3. CMD => seaJS
2.18.3. ES6****模块化语法

模块功能主要由两个命令构成: export 和 import 。
⚫ export 命令用于规定模块的对外接口
⚫ import 命令用于输入其他模块提供的功能

3ECMASript 7新特性

3.1.Array.prototype.includes

Includes 方法用来检测数组中是否包含某个元素,返回布尔类型值

**3.2.**指数操作符

在 ES7 中引入指数运算符「**」,用来实现幂运算,功能与 Math.pow 结果相同

javascript 复制代码
    <script>
        // includes   indexOf
        // const mingzhu = ['西游记','红楼梦','三国演义','水浒传'];

        //判断
        // console.log(mingzhu.includes('西游记'));
        // console.log(mingzhu.includes('金瓶梅'));

        // **
        console.log(2 ** 10);// 
        console.log(Math.pow(2, 10));
        
    </script>

4ECMASript 8新特性

4.1.asyncawait

async 和 await 两种语法结合可以让异步代码像同步代码一样

4.1.1.async****函数

  1. async 函数的返回值为 promise 对象,
  2. promise 对象的结果由 async 函数执行的返回值决定
javascript 复制代码
    <script>
        //async 函数
        async function fn(){
            // 返回一个字符串
            // return '清华大学';
            // 返回的结果不是一个 Promise 类型的对象, 返回的结果就是成功 Promise 对象
            // return;
            //抛出错误, 返回的结果是一个失败的 Promise
            // throw new Error('出错啦!');
            //返回的结果如果是一个 Promise 对象
            return new Promise((resolve, reject)=>{
                resolve('成功的数据');
                // reject("失败的错误");
            });
        }

        const result = fn();

        //调用 then 方法
        result.then(value => {
            console.log(value);
        }, reason => {
            console.warn(reason);
        })
    </script>

4.1.2.await****表达式

  1. await 必须写在 async 函数中

  2. await 右侧的表达式一般为 promise 对象

  3. await 返回的是 promise 成功的值

  4. await 的 promise 失败了 , 就会抛出异常 , 需要通过 try...catch 捕获处理

javascript 复制代码
    <script>
        //创建 promise 对象
        const p = new Promise((resolve, reject) => {
            // resolve("用户数据");
            reject("失败啦!");
        })

        // await 要放在 async 函数中.
        async function main() {
            try {
                let result = await p;
                //
                console.log(result);
            } catch (e) {
                console.log(e);
            }
        }
        //调用函数
        main();
    </script>

4.2.Object.valuesObject.entries

  1. Object.values() 方法返回一个给定对象的所有可枚举属性值的数组
  2. Object.entries() 方法返回一个给定对象自身可遍历属性 [key,value] 的数组

4.3.Object.getOwnPropertyDescriptors

该方法返回指定对象所有自身属性的描述对象

4.4 async与await封装AJAX请求

javascript 复制代码
    <script>
        // 发送 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) {
                            //成功啦
                            resolve(x.response);
                        }else{
                            //如果失败
                            reject(x.status);
                        }
                    }
                }
            })
        }
    
        //promise then 方法测试
        // sendAJAX("https://api.apiopen.top/getJoke").then(value=>{
        //     console.log(value);
        // }, reason=>{})
  
        // async 与 await 测试  axios
        async function main(){
            //发送 AJAX 请求
            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();
        
    </script>

4.5 ES8 对象方法扩展

javascript 复制代码
    <script>
        //声明对象
        const school = {
            name:"清华大学",
            cities:['北京','上海','深圳'],
            xueke: ['前端','Java','大数据','运维']
        };

        //获取对象所有的键
        // console.log(Object.keys(school));
        //获取对象所有的值
        // console.log(Object.values(school));
        //entries
        // console.log(Object.entries(school));
        //创建 Map
        // const m = new Map(Object.entries(school));
        // console.log(m.get('cities'));

        //对象属性的描述对象
        // console.log(Object.getOwnPropertyDescriptors(school));

        // const obj = Object.create(null, {
        //     name: {
        //         //设置值
        //         value: '清华大学',
        //         //属性特性
        //         writable: true,
        //         configurable: true,
        //         enumerable: true
        //     } 
        // });
    </script>

5ECMASript 9新特性

5.1.Rest/Spread****属性

Rest 参数与 spread 扩展运算符在 ES6 中已经引入,不过 ES6 中只针对于数组,在 ES9 中为对象提供了像数组一样的 rest 参数和扩展运算符。

javascript 复制代码
function connect({host, port, ...user}) {
 console.log(host);
 console.log(port);
 console.log(user);
}
connect({
 host: '127.0.0.1',
 port: 3306,
 username: 'root',
 password: 'root',
 type: 'master'
});

**5.2.**正则表达式命名捕获组

ES9 允许命名捕获组使用符号『 ?<name> 』 , 这样获取捕获结果可读性更强

javascript 复制代码
let str = '<a href="http://www.baidu.com">百度</a>';
const reg = /<a href="(?<url>.*)">(?<text>.*)<\/a>/;
const result = reg.exec(str);
console.log(result.groups.url);
console.log(result.groups.text);

**5.3.**正则表达式反向断言

ES9 支持反向断言,通过对匹配结果前面的内容进行判断,对匹配进行筛选。

javascript 复制代码
//声明字符串
let str = 'JS5211314 你知道么 555 啦啦啦';
//正向断言
const reg = /\d+(?=啦)/;
const result = reg.exec(str);
//反向断言
const reg = /(?<=么)\d+/;
const result = reg.exec(str);
console.log(result);

5.4.正则表达式dotAll****模式

正则表达式中点 . 匹配除回车外的任何单字符,标记『 s』改变这种行为,允许行终止符出现

javascript 复制代码
let str = `
<ul>
 <li>
 <a>肖生克的救赎</a>
 <p>上映日期: 1994-09-10</p>
 </li>
 <li>
 <a>阿甘正传</a>
 <p>上映日期: 1994-07-06</p>
 </li>
</ul>`;
//声明正则
const reg = /<li>.*?<a>(.*?)<\/a>.*?<p>(.*?)<\/p>/gs;
//执行匹配
const result = reg.exec(str);
let result;
let data = [];
while(result = reg.exec(str)){
 data.push({title: result[1], time: result[2]});
}
//输出结果
console.log(data);

6ECMASript 10新特性

6.1.Object.fromEntries

javascript 复制代码
    <script>
        //二维数组
        // const result = Object.fromEntries([
        //     ['name','北京大学'],
        //     ['xueke', 'Java,大数据,前端,云计算']
        // ]);

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

        //Object.entries ES8
        const arr = Object.entries({
            name: "北京大学"
        })
        console.log(arr);
    </script>

6.2.trimStart trimEnd

javascript 复制代码
    <script>    
        // trim
        let str = '   iloveyou   ';

        console.log(str);
        console.log(str.trimStart());
        console.log(str.trimEnd());
    </script>

6.3.Array.prototype.flat flatMap

javascript 复制代码
    <script>
        //flat 平
        //将多维数组转化为低位数组
        // const arr = [1,2,3,4,[5,6]];
        // const arr = [1,2,3,4,[5,6,[7,8,9]]];
        //参数为深度 是一个数字
        // console.log(arr.flat(2));  

        //flatMap
        const arr = [1,2,3,4];
        const result = arr.flatMap(item => [item * 10]);
        console.log(result);
    </script>

6.4.Symbol.prototype.description

javascript 复制代码
    <script>
        //创建 Symbol
        let s = Symbol('清华大学');

        console.log(s.description);
    </script>

7ECMASript 11新特性

7.1.String.prototype.matchAll

javascript 复制代码
    <script>
        let str = `<ul>
            <li>
                <a>肖生克的救赎</a>
                <p>上映日期: 1994-09-10</p>
            </li>
            <li>
                <a>阿甘正传</a>
                <p>上映日期: 1994-07-06</p>
            </li>
        </ul>`;

        //声明正则
        const reg = /<li>.*?<a>(.*?)<\/a>.*?<p>(.*?)<\/p>/sg

        //调用方法
        const result = str.matchAll(reg);

        // for(let v of result){
        //     console.log(v);
        // }

        const arr = [...result];

        console.log(arr);
    </script>

7.2. 类的私有属性

javascript 复制代码
    <script>
        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);
                console.log(this.#weight);
            }
        }

        //实例化
        const girl = new Person('小梅', 18, '45kg');

        // console.log(girl.name);
        // console.log(girl.#age);
        // console.log(girl.#weight);

        girl.intro();
    </script>

7.3.Promise.allSettled

javascript 复制代码
    <script>
        //声明两个promise对象
        const p1 = new Promise((resolve, reject)=>{
            setTimeout(()=>{
                resolve('商品数据 - 1');
            },1000)
        });

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

        //调用 allsettled 方法
        // const result = Promise.allSettled([p1, p2]);
        
        // const res = Promise.all([p1, p2]);

        console.log(res);

    </script>

7.4. 可选链操作符

javascript 复制代码
    <script>
        function main(config){
            // const dbHost = config && config.db && config.db.host;
            const dbHost = config?.db?.host;

            console.log(dbHost);
        }

        main({
            db: {
                host:'192.168.1.100',
                username: 'root'
            },
            cache: {
                host: '192.168.1.200',
                username:'admin'
            }
        })
    </script>

7.5. 动态 import 导入

javascript 复制代码
<body>
    <button id="btn">点击</button>
    <script src="./js/app.js" type="module"></script>
</body>

7.6.globalThis 对象

javascript 复制代码
    <script>
        console.log(globalThis);
    </script>
相关推荐
逐·風4 小时前
unity关于自定义渲染、内存管理、性能调优、复杂物理模拟、并行计算以及插件开发
前端·unity·c#
Devil枫4 小时前
Vue 3 单元测试与E2E测试
前端·vue.js·单元测试
尚梦5 小时前
uni-app 封装刘海状态栏(适用小程序, h5, 头条小程序)
前端·小程序·uni-app
GIS程序媛—椰子5 小时前
【Vue 全家桶】6、vue-router 路由(更新中)
前端·vue.js
前端青山6 小时前
Node.js-增强 API 安全性和性能优化
开发语言·前端·javascript·性能优化·前端框架·node.js
毕业设计制作和分享6 小时前
ssm《数据库系统原理》课程平台的设计与实现+vue
前端·数据库·vue.js·oracle·mybatis
从兄7 小时前
vue 使用docx-preview 预览替换文档内的特定变量
javascript·vue.js·ecmascript
清灵xmf8 小时前
在 Vue 中实现与优化轮询技术
前端·javascript·vue·轮询
大佩梨8 小时前
VUE+Vite之环境文件配置及使用环境变量
前端
GDAL8 小时前
npm入门教程1:npm简介
前端·npm·node.js