ES6-ES11新语法入门

237 阅读14分钟

ES6-ES11学习笔记

一、概述

1、什么是ECMA

ECMA(European Computer Manufacturers Association)中文名称为欧洲计算机制造商协会,这个组织的目标是评估、开发和认可电信和计算机标准。1994 年后该组织改名为 Ecma 国际;

2、什么是 ECMAScript

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

百度百科:baike.baidu.com/item/ECMASc…

3、什么是 ECMA-262

Ecma 国际制定了许多标准,而 ECMA-262 只是其中的一个,所有标准列表查看:

www.ecma-international.org/publication…

4、ECMA-262历史

ECMA-262(ECMAScript)历史版本查看网址:

www.ecma-international.org/publication…

版本时间概述
第 1 版1997年制定了语言的基本语法
第 2 版1998年较小改动
第 3 版1999年引入正则、异常处理、格式化输出等。IE 开始支持
第 4 版2007年过于激进,未发布
第 5 版2009年引入严格模式、JSON,扩展对象、数组、原型、字符串、日期方法
第 6 版2015年模块化、面向对象语法、Promise、箭头函数、let、const、数组解构赋值等等
第 7 版2016年幂运算符、数组扩展、Async/await 关键字
第 8 版2017年Async/await、字符串扩展
第 9 版2018年对象解构赋值、正则扩展
第 10版2019年扩展对象、数组方法
第 11版2020年链式操作、动态导入等
ES.next2020+动态指向下一个版本

注:从 ES6 开始,每年发布一个版本,版本号比年份最后一位大 1;

5、谁在维护 ECMA-262

TC39(Technical Committee 39)是推进 ECMAScript 发展的委员会。其会员都是公司(其中主要是浏览器厂商,有苹果、谷歌、微软、因特尔等)。TC39 定期召开会议,会议由会员公司的代表与特邀专家出席;

6、为什么要学习 ES6

ES6 的版本变动内容最多,具有里程碑意义;

ES6 加入许多新的语法特性,编程实现更简单、高效;

ES6 是前端发展趋势,就业必备技能;

7、ES6 兼容性

查看网址:kangax.github.io/compat-tabl…

二、ES6 新特性

0、功能概述

1、let 关键字

  • 声明局部变量;

2、const 关键字

  • 声明常量;

3、变量和对象的解构赋值

  • 简化变量声明

4、模板字符串

  • 声明自带格式的字符串;

5、简化对象写法

  • 简化对象写法;

6、箭头函数

  • 简化函数写法;

7、ES6中函数参数的默认值

  • 给函数的参数设置默认值;

8、rest参数

  • 拿到实参;

9、扩展运算符

  • 将一个数组转为用逗号分隔的参数序列;

10、Symbol

  • 表示独一无二的值;

11、迭代器

  • 用来遍历集合、数组等;

12、生成器

  • 是一种异步编程解决方案;

13、Promise

  • 非常强大的异步编程的新解决方案;

14、Set集合

  • 类似数组,但元素不重复的集合;

15、Map集合

  • 键值对集合;

16、class类

  • 像java实体类一样声明js类;

17、数值扩展

  • 增加一些数值相关的方法等;

18、对象扩展

  • 增加一些对象相关的方法等;

19、模块化

  • 模块化、组件化;

20、Babel对ES6模块化代码转换

  • 为了适配浏览器,将更新的ES规范转换成ES5规范;

21、ES6模块化引入NPM包

  • 像导入模块一样导入npm包;

1、let 关键字

1 、特性:

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

  1. 不允许重复声明;
  2. 块儿级作用域(局部变量);
  3. 不存在变量提升;
  4. 不影响作用域链;
  5. 特性学习代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>let</title>
</head>
<body>
    <script>
        //声明变量
        let a;
        let b,c,d;
        let e = 100;
        let f = 521, g = 'iloveyou', h = [];

        //1. 变量不能重复声明
        // let star = '罗志祥';
        // let star = '小猪';

        //2. 块儿级作用域  全局, 函数, eval
        // if else while for 
        // {
        //     let girl = '周扬青';
        // }
        // console.log(girl);

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

        //4. 不影响作用域链,即作用域链的特性与var相同
        {
            let school = '尚硅谷';
            function fn(){
                console.log(school);
            }
            fn();
        }

    </script>
</body>
</html>

let案例:点击div更改颜色

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>点击 DIV 换色</title>
    <link crossorigin="anonymous" href="https://cdn.bootcss.com/twitter-bootstrap/3.3.7/css/bootstrap.min.css"
        rel="stylesheet">
    <style>
        .item {
            width: 100px;
            height: 50px;
            border: solid 1px rgb(42, 156, 156);
            float: left;
            margin-right: 10px;
        }
    </style>
</head>

<body>
    <div class="container">
        <h2 class="page-header">点击切换颜色</h2>
        <div class="item"></div>
        <div class="item"></div>
        <div class="item"></div>
    </div>
    <script>
        //获取div元素对象
        let items = document.getElementsByClassName('item');

        //遍历并绑定事件 在每次循环下都定义了一个let i 互不影响
		//若使用 var i ;i就是 全局的 当点击时 i=items.length 无法使div变色,所以只能和this搭配
        for(let i = 0;i<items.length;i++){
            items[i].onclick = function(){
                //修改当前元素的背景颜色
                // this.style.background = 'pink';
                items[i].style.background = 'pink';
            }
        }
        
    </script>
</body>

</html>

2、const 关键字

特性:

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

  1. 声明必须赋初始值;

  2. 标识符一般为大写(习惯);

  3. 不允许重复声明;

  4. 值不允许修改;

  5. 块儿级作用域(局部变量);

  6. 对于数组和对象的元素修改, 不算做对常量的修改, 不会报错 const 指向的数组变量实质是地址 ,修改数组里面的内容不会改变地址

  7. 特性学习代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>const 定义常量</title>
</head>
<body>
    <script>
        //声明常量
        const SCHOOL = '尚硅谷';

        //1. 一定要赋初始值
        // const A;
        //2. 一般常量使用大写(潜规则)
        // const a = 100;
        //3. 常量的值不能修改
        // SCHOOL = 'ATGUIGU';
        //4. 块儿级作用域
        // {
        //     const PLAYER = 'UZI';
        // }
        // console.log(PLAYER);
        //5. 对于数组和对象的元素修改, 不算做对常量的修改, 不会报错
        const TEAM = ['UZI','MXLG','Ming','Letme'];
        // TEAM.push('Meiko');

        
    </script>
</body>
</html>

应用场景:

  • 声明对象类型使用 const,非对象类型声明选择 let
  • 以后声明变量使用 let 就对了

3、变量和对象的解构赋值

1、什么是解构赋值:

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

代码演示及相关说明:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>变量的解构赋值</title>
</head>
<body>
    <script>
        //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);
        // xiaopin();



    </script>
</body>

</html>
 

应用场景:

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

4、模板字符串

概述:

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

  • 字符串中可以出现换行符;

  • 可以使用 ${xxx} 形式引用变量;

代码演示及相关说明:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>模板字符串</title>
</head>

<body>
    <script>
        // ES6 引入新的声明字符串的方式 『``』 '' "" 
        //1. 声明
        // let str = `我也是一个字符串哦!`;
        // console.log(str, typeof str);

        //2. 内容中可以直接出现换行符
        // let str = `<ul>
        //             <li>沈腾</li>
        //             <li>玛丽</li>
        //             <li>魏翔</li>
        //             <li>艾伦</li>
        //             </ul>`;

        // console.log(str);
        //3. 变量拼接
        let lovest = '魏翔';
        let out = `${lovest}是我心目中最搞笑的演员!!`;
        console.log(out);
    </script>
</body>

</html>

应用场景:

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

5、简化对象写法

概述:

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

代码示例及相关说明:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>简化对象写法</title>
</head>
<body>
    <script>
        //ES6 允许在大括号里面,直接写入变量和函数,作为对象的属性和方法。
        //这样的书写更加简洁
        let name = '尚硅谷';
        let change = function(){
            console.log('我们可以改变你!!');
        }

        const school = {
            name,
            change,
            // improve: function() {
            //     console.log("我们可以提高你的技能");
            // }
            //可以简化为:
            improve(){
                console.log("我们可以提高你的技能");
            }
        }

        console.log(school);

    </script>
</body>
</html>

6、箭头函数

概述:

ES6允许使用箭头(=>)定义函数,箭头函数提供了一种更加简洁的函数书写方式,箭头函数多用于匿 名函数的定义;

箭头函数的注意点:

  1. 如果形参只有一个,则小括号可以省略;
  2. 函数体如果只有一条语句,则花括号可以省略,函数的返回值为该条语句的执行结果(花括号省略后 return 必须省略);
  3. 箭头函数 this 指向声明时所在作用域下 this 的值;箭头函数的this是静态的,始终指向函数声明时所在作用域下的this的值;
  4. 原始的function 的 this是看 调用这个this的属性的函数属于哪一个对象
  5. 箭头函数不能作为构造函数实例化;
  6. 不能使用 arguments变量;
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>箭头函数</title>
</head>

<body>
    <script>
        // ES6 允许使用「箭头」(=>)定义函数。
        //声明一个函数
        // let fn = function(){

        // }
        // let fn = (a,b) => {
        //     return a + b;
        // }
        //调用函数
        // let result = fn(1, 2);
        // console.log(result);


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

        //设置 window 对象的 name 属性
        window.name = '尚硅谷';
        const school = {
            name: "ATGUIGU"
        }

        //直接调用
        // getName();
        // getName2();

        //call 方法调用
        // getName.call(school);
        // getName2.call(school);

        //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;
                
            console.log(pow(8));

    </script>
</body>

</html>

箭头函数应用示例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>箭头函数实践</title>
    <style>
        div {
            width: 200px;
            height: 200px;
            background: #58a;
        }
    </style>
</head>
<body>
    <div id="ad"></div>
    <script>
        //需求-1  点击 div 2s 后颜色变成『粉色』
        //获取元素
        let ad = document.getElementById('ad');
        //绑定事件
        ad.addEventListener("click", function(){
            //保存 this 的值
            // let _this = this;
            //这个this是 ad
            //定时器
            setTimeout(() => {
                //修改背景颜色 this
                //若这里不是箭头函数,this指向的是windows
                //因为setTimeout是属于windows的方法
                //箭头函数的this是这个setTimeout所在作用域的this,即ad
                // console.log(this);
                //若是使用function 解决方法是使用_this把外层this取过来
                // _this.style.background = 'pink';
                this.style.background = 'pink';
            }, 2000);
        });

        //需求-2  从数组中返回偶数的元素
        const arr = [1,6,9,10,100,25];
        // const result = arr.filter(function(item){
        //     if(item % 2 === 0){
        //         return true;
        //     }else{
        //         return false;
        //     }
        // });
        
        const result = arr.filter(item => item % 2 === 0);

        console.log(result);

        // 箭头函数适合与 this 无关的回调. 定时器, 数组的方法回调
        // 箭头函数不适合与 this 有关的回调.  DOM元素事件回调, 对象的方法

    </script>
</body>

</html>
  • 箭头函数适合与 this 无关的回调. 定时器, 数组的方法回调
  • 箭头函数不适合与 this 有关的回调. DOM元素事件回调, 对象的方法

7、ES6中函数参数的默认值

  1. ES6 允许给函数参数赋值初始值
  2. 形参初始值 具有默认值的参数, 一般位置要靠后(潜规则)
  3. 与解构赋值结合
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>函数参数默认值</title>
</head>

<body>
    <script>
        // ES6 允许给函数参数赋值初始值
        // 1. 形参初始值 具有默认值的参数, 一般位置要靠后(潜规则)
        // function add(a,b,c=10) {
        //     return a + b + c;
        // }
        // let result = add(1,2);
        // console.log(result);

        //2. 与解构赋值结合
        function connect({host = "127.0.0.1",username,password,port}) {
            console.log(host)
            console.log(username)
            console.log(password)
            console.log(port)
        }
        connect({
            host: 'atguigu.com',
            username: 'root',
            password: 'root',
            port: 3306
        })
    </script>
</body>

</html>

8、rest参数

概述: ES6 引入 rest 参数,用于获取函数的实参,用来代替 arguments; rest 参数必须要放到参数最后

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>rest参数</title>
</head>
<body>
    <script>
        // ES6 引入 rest 参数,用于获取函数的实参,用来代替 arguments
        // ES5 获取实参的方式
        // function date(){
        //     console.log(arguments);
        // }
        // date('白芷','阿娇','思慧');

        // rest 参数
        //arguments是伪数组 ,rest是数组
        function date(...args){
            console.log(args);// filter some every map 
        }
        date('阿娇','柏芝','思慧');

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

    </script>
</body>
</html>

9、扩展运算符

介绍:

... 扩展运算符能将数组转换为逗号分隔的参数序列;

『扩展运算符』 可以对 集合实现了 iterator接口的对象操作

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

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>扩展运算符</title>
</head>
<body>
    <script>
        // 『...』 扩展运算符能将『数组』转换为逗号分隔的『参数序列』
        //声明一个数组 ...
        const tfboys = ['易烊千玺','王源','王俊凯'];
        // => '易烊千玺','王源','王俊凯'

        // 声明一个函数
        function chunwan(){
            console.log(arguments);
        }

        chunwan(...tfboys);// chunwan('易烊千玺','王源','王俊凯')

        

    </script>
</body>
</html>

扩展运算符的应用

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>扩展运算符应用</title>
</head>
<body>
    <div></div>
    <div></div>
    <div></div>
    <script>
        //1. 数组的合并 情圣  误杀  唐探
        // const kuaizi = ['王太利','肖央'];
        // const fenghuang = ['曾毅','玲花'];
        // // const zuixuanxiaopingguo = kuaizi.concat(fenghuang);
        // const zuixuanxiaopingguo = [...kuaizi, ...fenghuang];
        // console.log(zuixuanxiaopingguo);

        //2. 数组的克隆
        // const sanzhihua = ['E','G','M'];
        // //const sanyecao = sanzhihua;这是一个浅拷贝,修改sanyecao ,sanzhihua也会改变
        // const sanyecao = [...sanzhihua];//  ['E','G','M']
        // console.log(sanyecao);

        //3. 将伪数组转为真正的数组
        const divs = document.querySelectorAll('div');
        const divArr = [...divs];
        console.log(divArr);// arguments
    
    </script>
</body>
</html>

10、Symbol

Symbol 概述:

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

Symbol 特点:

  1. Symbol 的值是唯一的,用来解决命名冲突的问题;

  2. Symbol 值不能与其他数据进行运算;

  3. Symbol 定义的对象属性不能使用for…in循环遍历 ,但是可以使用Reflect.ownKeys 来获取对象的所有键名;

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>symbol</title>
</head>
<body>
    <script>
        //创建Symbol
        let s = Symbol();
        console.log(s, typeof s);
        let s2 = Symbol('尚硅谷');
        let s3 = Symbol('尚硅谷');
        console.log(s2===s3);

        //Symbol.for 创建
        let s4 = Symbol.for('尚硅谷');
        let s5 = Symbol.for('尚硅谷');
        console.log(s4===s5);

        //不能与其他数据进行运算
        //    let result = s + 100;
        //    let result = s > 100;
        //    let result = s + s;

        //记忆7个数据类型 你是如此nb
        // USONB  you are so niubility 
        // u  undefined
        // s  string  symbol
        // o  object
        // n  null number
        // b  boolean

    </script>
</body>
</html> 

Reflect.ownKeys 来获取对象的所有键名

class Person {
    constructor() {
        this.a = 1
        this.b = 2
        this[Symbol.for('a')] = 3
        this[Symbol()] = 'test'
        this[Symbol()] = 'sucess'
    }
}

let person = new Person;

for (var a in person) {
    console.log(a + ':' + person[a]);
}
console.log('\n');
console.log('属性:');
console.log(Reflect.ownKeys(person));

//取出第一个Symbol() 的值
let t = Reflect.ownKeys(person)[3]
console.log(person[t] + '\n');


//遍历
for (var i of Reflect.ownKeys(person)) {
    console.log(i);
    console.log(`: ${person[i]}\n`);
}

执行结果:

image-20220226115230469

对象添加symbol 类型的属性

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Symbol 创建对象属性</title>
</head>

<body>
    <script>
        //向对象中添加方法 up down
        let game = {
            name: '俄罗斯方块',
            up: function() {},
            down: function() {}
        };

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

        // game[methods.up] = function(){
        //     console.log("我可以改变形状");
        // }

        // game[methods.down] = function(){
        //     console.log("我可以快速下降!!");
        // }

        // console.log(game);

        //

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

        console.log(youxi)
        youxi[say]();
    </script>
</body>

</html>
内置Symbol的值调用时机
Symbol.hasInstance当其他对象使用 instanceof 运算符,判断是否为该对象的实例时,会调用这个方法
Symbol.isConcatSpreadable对象的 Symbol.isConcatSpreadable 属性等于的是一个布尔值,表示该对象用于Array.prototype.concat()时,是否可以展开。
Symbol.species创建衍生对象时,会使用该属性
Symbol.match当执行 str.match(myObject) 时,如果该属性存在,会调用它,返回该方法的返回值。
Symbol.replace当该对象被 str.replace(myObject)方法调用时,会返回该方法的返回值。
Symbol.search当该对象被 str. search (myObject)方法调用时,会返回该方法的返回值。
Symbol.split当该对象被 str. split (myObject)方法调用时,会返回该方法的返回值。
Symbol.iterator对象进行 for…of 循环时,会调用 Symbol.iterator 方法,返回该对象的默认遍历器
Symbol.toPrimitive该对象被转为原始类型的值时,会调用这个方法,返回该对象对应的原始类型值。
Symbol. toStringTag在该对象上面调用 toString 方法时,返回该方法的返回值
Symbol. unscopables该对象指定了使用 with 关键字时,哪些属性会被 with环境排除。

特别的: Symbol内置值的使用,都是作为某个对象类型的属性去使用; 【拓展对象功能】

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Symbol内置属性</title>
</head>

<body>
    <script>
        class Person {
            static[Symbol.hasInstance](param) {
                console.log(param);
                console.log("我被用来检测类型了");
                return false;
            }
        }

        let o = {};

        console.log(o instanceof Person);

        // const arr = [1,2,3];
        // const arr2 = [4,5,6];
        // arr2[Symbol.isConcatSpreadable] = false;
        // console.log(arr.concat(arr2));
    </script>
</body>

</html>
//一些不理解的代码
//Symbol内置值给类使用时,需要作为静态属性
        class Person {

        }
        function Person1() {

        }
        class Person2 {
            static [Symbol.hasInstance](param) {
                console.log(param);
                console.log("我被用来检测类型了");
                return false;
            }
        }

        Person[Symbol.hasInstance] = (param) => {
            console.log(param);
            console.log("我被用来检测类型了");
            return true;
        }
        Person1[Symbol.hasInstance] = (param) => {
            console.log(param);
            console.log("我被用来检测类型了");
            return true;
        }

        let o = {};

        console.log(Person); console.log(Person1); console.log(Person2);
        console.log(Person[Symbol.hasInstance]);
        console.log(Person1[Symbol.hasInstance]);
        console.log(Person2[Symbol.hasInstance]);


        console.log(o instanceof Person);
        console.log(o instanceof Person1);
        console.log(o instanceof Person2);

11、迭代器

概述:

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

特性:

ES6 创造了一种新的遍历命令 for...of 循环,Iterator 接口主要供 for...of 消费; 原生具备 iterator 接口的数据(可用 for of 遍历):

工作原理:

  1. 创建一个指针对象,指向当前数据结构的起始位置;

  2. 第一次调用对象的 next 方法,指针自动指向数据结构的第一个成员;

  3. 接下来不断调用 next 方法,指针一直往后移动,直到指向最后一个成员;

  4. 每调用 next 方法返回一个包含 value 和 done 属性的对象;

注:需要自定义遍历数据的时候,要想到迭代器;

代码示例及相关说明:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>迭代器</title>
</head>

<body>
    <script>
        //声明一个数组
        const xiyou = ['唐僧', '孙悟空', '猪八戒', '沙僧'];

        //使用 for...of 遍历数组
        for (let v of xiyou) {
            console.log(v);
        }
        console.log(xiyou);
        let iterator = xiyou[Symbol.iterator]();
        console.log(iterator);
        //调用对象的next方法
        console.log(iterator.next());
        console.log(iterator.next());
        console.log(iterator.next());
        console.log(iterator.next());
        console.log(iterator.next());
        // 重新初始化对象,指针也会重新回到最前面 
        let iterator1 = xiyou[Symbol.iterator](); 
		console.log(iterator1.next());
    </script>
</body>

</html>

迭代器自定义遍历对象:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>自定义遍历数据</title>
</head>

<body>
    <script>
        //声明一个对象
        const banji = {
            name: "终极一班",
            stus: [
                'xiaoming',
                'xiaoning',
                'xiaotian',
                'knight'
            ],
            [Symbol.iterator]() {
                //索引变量
                let index = 0;
                //
                let _this = this;
                return {
                    next: function () {
                        if (index < _this.stus.length) {
                            const result = { value: _this.stus[index], done: false };
                            //下标自增
                            index++;
                            //返回结果
                            return result;
                        }else{
                            return {value: undefined, done: true};
                        }
                    }
                };
            }
        }

        //遍历这个对象 
        for (let v of banji) {
            console.log(v);
        }
    </script>
</body>

</html>

12、生成器

概述:

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

next()方法是可以传入参数的,传入的参数作为第一条(上一条)语句yield 111的返回 结果

解决回调地狱

1)生成器函数声明与调用

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>生成器</title>
</head>

<body>
    <script>
        //生成器其实就是一个特殊的函数
        //异步编程  纯回调函数  node fs  ajax mongodb
        //函数代码的分隔符
        function* gen() {
            // console.log(111);
            yield '一只没有耳朵';
            // console.log(222);
            yield '一只没有尾部';
            // console.log(333);
            yield '真奇怪';
            // console.log(444);
        }

        let iterator = gen();
        console.log(iterator.next());
        console.log(iterator.next());
        console.log(iterator.next());
        console.log(iterator.next());

        //遍历
        // for(let v of gen()){
        //     console.log(v);
        // }
    </script>
</body>

</html>

2)生成器函数的参数传递:


<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>生成器函数参数</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 iterator = gen('AAA');
        console.log(iterator.next());// 会执行yield 111;
        // next()方法是可以传入参数的,传入的参数作为第一条(上一条)语句yield 111的返回 结果
        console.log(iterator.next('BBB'));// 会执行yield 222;并且传入的BBB 是语句yield 111 返回的值
		
        console.log(iterator.next('CCC'));
        console.log(iterator.next('DDD'));
    </script>
</body>

</html>

3)生成器应用实例1,解决回调地狱问题

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>生成器函数实例</title>
</head>

<body>
    <script>
        // 异步编程  文件操作 网络操作(ajax, request) 数据库操作
        // 1s 后控制台输出 111  2s后输出 222  3s后输出 333 
        // 回调地狱
        // setTimeout(() => {
        //     console.log(111);
        //     setTimeout(() => {
        //         console.log(222);
        //         setTimeout(() => {
        //             console.log(333);
        //         }, 3000);
        //     }, 2000);
        // }, 1000);

        function one() {
            setTimeout(() => {
                console.log(111);
                iterator.next();
            }, 1000)
        }

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

        function three() {
            setTimeout(() => {
                console.log(333);
                iterator.next();
            }, 3000)
        }

        function* gen() {
            yield one();
            yield two();
            yield three();
        }

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

</html>

4)生成器应用实例2 顺序获得用户数据 订单数据 商品数据

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>生成器函数</title>
</head>
<body>
    <script>
        //模拟获取  用户数据  订单数据  商品数据 
        function getUsers(){
            setTimeout(()=>{
                let data = '用户数据';
                //调用 next 方法, 并且将数据传入
                iterator.next(data);
            }, 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();
            let orders = yield getOrders();
            let goods = yield getGoods();
        }

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

        

    </script>
</body>
</html>

13、Promise

概述

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

  1. Promise 构造函数: Promise (excutor) {};

  2. Promise.prototype.then 方法;

  3. Promise.prototype.catch 方法;

1)基本使用

<!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 p = new Promise(function(resolve, reject){
            setTimeout(function(){
                let data = '数据库中数据';
                let err = '调取失败了';

                if(1/*写为0表示失败*/){
             // 调用resolve,这个Promise 对象的状态就会变成成功
                    resolve(data);
                }else{
             // 调用reject,这个Promise 对象的状态就会变成成功
                    reject(err);
                }
            },1000);
        });
        p.then(value=>{
            console.log(value);
        },reason=>{
            console.log(reason);
        }
        );

    </script>
</body>
</html>

2)Promise封装读取文件:

一般读取文件写法:(需要node.js 环境 ,运行方式:在终端: node 文件名)

//1. 引入 fs 模块
const fs = require('fs');

//2. 调用方法读取文件
fs.readFile('./resources/为学.md', (err, data)=>{
    //如果失败, 则抛出错误
    if(err) throw err;
    //如果没有出错, 则输出内容
    console.log(data.toString());
});

Promise封装:

//1. 引入 fs 模块
const fs = require('fs');

//2. 调用方法读取文件
// fs.readFile('./resources/为学.md', (err, data)=>{
//     //如果失败, 则抛出错误
//     if(err) throw err;
//     //如果没有出错, 则输出内容
//     console.log(data.toString());
// });

//3. 使用 Promise 封装
const p = new Promise(function(resolve, reject){
    fs.readFile("./resources/为学.md", (err, data)=>{
        //判断如果失败
        if(err) reject(err);
        //如果成功
        resolve(data);
    });
});

p.then(function(value){
    console.log(value.toString());
}, function(reason){
    console.log("读取失败!!");
});

3)Promise封装Ajax请求:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>发送 AJAX 请求</title>
</head>

<body>
    <script>
        // 接口地址: https://api.apiopen.top/getJoke
        const p = new Promise((resolve, reject) => {
            //1. 创建对象
            const xhr = new XMLHttpRequest();

            //2. 初始化
            xhr.open("GET", "https://api.apiopen.top/getJoke");

            //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>
</body>

</html>

4)Promise.prototype.then 返回值为Promise

代码实现及相关说明:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Promise.prototype.then</title>
</head>
<body>
    <script>
        //创建 promise 对象
        const p = new Promise((resolve, reject)=>{
            setTimeout(()=>{
                resolve('用户数据');
                // reject('出错啦');
            }, 1000)
        });

        //调用 then 方法  then方法的返回结果是 Promise 对象, 
        //对象状态由回调函数的执行结果决定
       

        // const result = p.then(value => {
        //     console.log(value);
        //      //1. 如果回调函数中返回的结果是 非 promise 类型的属性, 
        //      //状态为成功fulfilled, 返回值为对象的成功的值
        //     // return 'iloveyou';
        //     //2. 是 promise 对象
        //     // 此Promise对象的状态决定返回Promise对象p的状态
        //     // return new Promise((resolve, reject)=>{
        //     //     // resolve('ok');
        //     //     reject('error');
        //     // });
        //     //3. 抛出错误
        //     //返回Promise对象的状态是rejected
        //
        //     // throw new Error('出错啦!');
        //     throw '出错啦!';
        // }, reason=>{
        //     console.warn(reason);
        // });

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

        }).then(value=>{

        });


    </script>
</body>
</html>

5)Promise-catch方法:相当于Promise.prototype.then:只有第二个参数

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>catch方法</title>
</head>
<body>
    <script>
        const p = new Promise((resolve, reject)=>{
            setTimeout(()=>{
                //设置 p 对象的状态为失败, 并设置失败的值
                reject("出错啦!");
            }, 1000)
        });

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

        p.catch(function(reason){
            console.warn(reason);
        });
    </script>
</body>
</html>

 //catch 能捕捉某个阶段的错误,并处理
		const p = new Promise(function (resolve, reject) {
            let data = 'success'
            resolve(data)
            // reject('读取失败')
        })


        p.then((value) => {
            // throw '4'
            // return 5
        }).then(value => {
            // throw 6
            return 4
        }).catch(err =>
            console.log(err)
        )

6)Promise读取多个文件实践练习:(node.js环境在终端运行)

//引入 fs 模块
const fs = require("fs");

// //这种写法不断嵌套,层数太多的话代码不简洁,称为回调地狱
// fs.readFile('./resources/为学.md', (err, data1)=>{
//     fs.readFile('./resources/插秧诗.md', (err, data2)=>{
//         fs.readFile('./resources/观书有感.md', (err, data3)=>{
//             let result = data1 + '\r\n' +data2  +'\r\n'+ data3;
//             console.log(result);
//         });
//     });
// });

//使用 promise 实现
const p = new Promise((resolve, reject) => {
    fs.readFile("./resources/为学.md", (err, data) => {
        resolve(data);
    });
});

p.then(value => {
    return new Promise((resolve, reject) => {
        fs.readFile("./resources/插秧诗.md", (err, data) => {
            resolve([value, data]);
        });
    });
}).then(value => {
    return new Promise((resolve, reject) => {
        fs.readFile("./resources/观书有感.md", (err, data) => {
            //压入
            value.push(data);
            resolve(value);
        });
    })
}).then(value => {
    console.log(value.join('\r\n'));
});

14、Set集合

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

  1. size 返回集合的元素个数;
  2. add 增加一个新元素,返回当前集合;
  3. delete 删除元素,返回 boolean 值;
  4. has 检测集合中是否包含某个元素,返回 boolean 值;
  5. clear 清空集合,返回 undefined;

基本使用:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>集合</title>
</head>
<body>
    <script>
        //声明一个 set
        let s = new Set();
        let s2 = new Set(['大事儿','小事儿','好事儿','坏事儿','小事儿']);

        //元素个数
        // console.log(s2.size);
        //添加新的元素
        // s2.add('喜事儿');
        //删除元素
        // s2.delete('坏事儿');
        //检测
        // console.log(s2.has('糟心事'));
        //清空
        // s2.clear();
        // console.log(s2);

        for(let v of s2){
            console.log(v);
        }
        
    </script>
</body>
</html>

Set集合实践:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Set 实践</title>
</head>
<body>
    <script>
        let arr = [1,2,3,4,5,4,3,2,1];
        //1. 数组去重
        // let result = [...new Set(arr)];
        // console.log(result);
        //2. 交集
        let arr2 = [4,5,6,5,6];
        // let result = [...new Set(arr)].filter(item => {
        //     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);

    </script>
</body>

</html>

15、Map集合

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

Map 的属性和方法:

  1. size 返回 Map 的元素个数;
  2. set 增加一个新元素,返回当前 Map;
  3. get 返回键名对象的键值;
  4. has 检测 Map 中是否包含某个元素,返回 boolean 值;
  5. clear 清空集合,返回 undefined;

简单使用:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Map</title>
</head>
<body>
    <script>
        //声明 Map
        let m = new Map();

        //添加元素
        m.set('name','尚硅谷');
        m.set('change', function(){
            console.log("我们可以改变你!!");
        });
        let key = {
            school : 'ATGUIGU'
        };
        m.set(key, ['北京','上海','深圳']);

        //size
        // console.log(m.size);

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

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

        //清空
        // m.clear();

        //遍历 每个v都是一个二元数组,第一个元素是键值,第二个元素是value
        for(let v of m){
            console.log(v);
        }

        // console.log(m);

    </script>
</body>
</html>

16、class类

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

知识点:

  1. class 声明类;
  2. constructor 定义构造函数初始化;
  3. extends 继承父类;
  4. super 调用父级构造方法;
  5. static 定义静态方法和属性;
  6. 父类方法可以重写;

1)class初体验:

代码实现:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>类声明</title>
</head>
<body>
    <script>
        //手机
        function Phone(brand, price){
            this.brand = brand;
            this.price = price;
        }

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

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

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

            //方法必须使用该语法, 不能使用 ES5 的对象完整形式
            call(){
                console.log("我可以打电话!!");
            }
        }

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

        console.log(onePlus);
    </script>
</body>
</html>

2)class静态成员:

代码实现:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>静态成员</title>
</head>
<body>
    <script>
        // function Phone(){

        // }
        // Phone.name = '手机';
        // Phone.change = function(){
        //     console.log("我可以改变世界");
        // }
        // Phone.prototype.size = '5.5inch';

        // let nokia = new Phone();

        // console.log(nokia.name);
        // // nokia.change();
        // console.log(nokia.size);

        class Phone{
            //静态属性
            static name = '手机';
            static change(){
                console.log("我可以改变世界");
            }
        }

        let nokia = new Phone();
        console.log(nokia.name);
        console.log(Phone.name);
    </script>
</body>
</html>

3)ES5构造函数实现继承

代码实现:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>对象继承</title>
</head>
<body>
    <script>
        //手机
        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);
            this.color = color;
            this.size = size;
        }

        //设置子级构造函数的原型
        // SmartPhone.prototype = new Phone;
        // SmartPhone.prototype.constructor = SmartPhone;
        // 上面两句话是老师讲得 ,下面一句是我自己的理解
         SmartPhone1.prototype.__proto__ = (new Phone).__proto__;

        //声明子类的方法
        SmartPhone.prototype.photo = function(){
            console.log("我可以拍照")
        }

        SmartPhone.prototype.playGame = function(){
            console.log("我可以玩游戏");
        }

        const chuizi = new SmartPhone('锤子',2499,'黑色','5.5inch');

        console.log(chuizi);

    </script>
</body>
</html>

4)ES6class类继承(及其方法的重写)

重写后不能再调用父类的方法

代码实现:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>类继承-2</title>
</head>
<body>
    <script>
        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);// Phone.call(this, brand, price)
                this.color = color;
                this.size = size;
            }

            photo(){
                console.log("拍照");
            }

            playGame(){
                console.log("玩游戏");
            }
            // 子类对父类方法重写 
            // 直接写,直接覆盖 
            // 注意:子类无法调用父类同名方法
            call(){
                console.log('我可以进行视频通话');
            }
        }

        const xiaomi = new SmartPhone('小米',799,'黑色','4.7inch');
        // console.log(xiaomi);
        xiaomi.call();
        xiaomi.photo();
        xiaomi.playGame();
    </script>
</body>
</html>

5)class的set-get

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>get 和 set</title>
</head>
<body>
    <script>
        // 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';
    </script>
</body>
</html>
<!--根据自己的理解写点代码,有了新感悟会修改-->
<!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>


        // get 和 set  
        class Phone {
            constructor() {
                this.yincang = {}
                this.yincang.price = 'free'
            }
            get price() {
                console.log("价格属性被读取了");
                return this.yincang.price;
            }

            set price(newVal) {
                console.log('价格属性被修改了');
                this.yincang.price = newVal
            }
        }

        //实例化对象
        let s = new Phone();

        // console.log(s.price);
        s.price = 'free';



    </script>
</body>

</html>

17、数值扩展

Number.EPSILON: Number.EPSILON 是 JavaScript 表示的最小精度; EPSILON 属性的值接近于 2.2204460492503130808472633361816E-16;

二进制和八进制: ES6 提供了二进制和八进制数值的新的写法,分别用前缀 0b 和 0o 表示; 当然八进制也可以只加一个前缀0

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

Number.parseInt() 与 Number.parseFloat(): ES6 将全局方法 parseInt 和 parseFloat,移植到 Number 对象上面,使用不变;

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

**Math.trunc: **
用于去除一个数的小数部分,返回整数部分;

Math.sign
判断一个数到底为正数 负数 还是零

代码实现和相关说明: 代码实现:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>数值扩展</title>
</head>
<body>
    <script>
        //0. 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);
        // console.log(equal(0.1 + 0.2, 0.3))

        //1. 二进制和八进制
        // let b = 0b1010;
        // let o = 0o777;
        // let d = 100;
        // let x = 0xff;
        // console.log(x);

        //2. Number.isFinite  检测一个数值是否为有限数
        // console.log(Number.isFinite(100));
        // console.log(Number.isFinite(100/0));
        // console.log(Number.isFinite(Infinity));
        
        //3. Number.isNaN 检测一个数值是否为 NaN 
        // console.log(Number.isNaN(123)); 

        //4. Number.parseInt Number.parseFloat字符串转整数
        // console.log(Number.parseInt('5211314love'));
        // console.log(Number.parseFloat('3.1415926神奇'));

        //5. Number.isInteger 判断一个数是否为整数
        // console.log(Number.isInteger(5));
        // console.log(Number.isInteger(2.5));

        //6. Math.trunc 将数字的小数部分抹掉  
        // console.log(Math.trunc(3.5));

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

    </script>
</body>
</html>

18、对象扩展

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

  1. Object.is 比较两个值是否严格相等,与『===』行为基本一致(+0 与 NaN);
  2. Object.assign 对象的合并,将源对象的所有可枚举属性,复制到目标对象;
  3. proto、setPrototypeOf、 setPrototypeOf 可以直接设置对象的原型;

代码实现及相关说明: 代码实现:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>对象方法扩展</title>
</head>
<body>
    <script>
        //1. Object.is 判断两个值是否完全相等 
        // console.log(Object.is(120, 120));// === 
        // console.log(Object.is(NaN, NaN));// === 
        // console.log(NaN === NaN);// === 
        // // NaN与任何数值做===比较都是false,跟他自己也如此!

        //2. Object.assign 对象的合并 对象的合并,将源对象的所有可枚举属性,复制到目标对象;
        // const config1 = {
        //     host: 'localhost',
        //     port: 3306,
        //     name: 'root',
        //     pass: 'root',
        //     test: 'test'
        // };
        // const config2 = {
        //     host: 'http://atguigu.com',
        //     port: 33060,
        //     name: 'atguigu.com',
        //     pass: 'iloveyou',
        //     test2: 'test2'
        // }
        // // 如果前边有后边没有会保留,
        // // 如果前后都有,后面的会覆盖前面的
        // // 如果前边没有后边有会添加
        // console.log(Object.assign(config1, config2));

        //3. Object.setPrototypeOf 设置原型对象  Object.getPrototypeof
        const school = {
            name: '尚硅谷'
        }
        const cities = {
            xiaoqu: ['北京','上海','深圳']
        }
        // 并不建议这么做
        // 应该创建对象的时候就设置好原型
        Object.setPrototypeOf(school, cities);
        console.log(Object.getPrototypeOf(school));
        console.log(school);


        
    </script>
</body>
</html>

Object.create()方法创建一个新对象,使用现有的对象来提供新创建的对象的__proto__。

        const person = {
            isHuman: false,
            printIntroduction: function () {
                console.log(`My name is ${this.name}. Am I human? ${this.isHuman}`);
            }
        };

        const me = Object.create(person);
        me.name = 'Matthew'; // "name" is a property set on "me", but not on "person"
        me.isHuman = true; // inherited properties can be overwritten

        me.printIntroduction();
        // expected output: "My name is Matthew. Am I human? true"

19、模块化

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

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

  1. 防止命名冲突;
  2. 代码复用;
  3. 高维护性;

模块化规范产品: ES6 之前的模块化规范有:

  1. CommonJS => NodeJS、Browserify(前端代码打包);
  2. AMD => requireJS;
  3. CMD => seaJS;

ES6 模块化语法: 模块功能主要由两个命令构成:export 和 import

  • export 命令用于规定模块的对外接口(导出模块);
  • import 命令用于输入其他模块提供的功能(导入模块);

三种暴露方式和对应导入方式简单使用: m.js(导出模块):

模块化.html(导入和使用模块):

ES6暴露数据语法汇总: m1.js(逐个导出模块):

//分别暴露
export let school = '尚硅谷';
export function teach() {
    console.log("我们可以教给你开发技能");
}

m2.js(统一导出模块):

//统一暴露
let school = '尚硅谷';

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

//
export {school, findJob};

m3.js(默认导出模块):

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

模块化.html(导入和使用模块)(好像有跨域的问题,需要构建服务器打开html文件,否则会报错):

三种导入方式

  1. 通用导入方式
  2. 解构赋值形式
  3. 简便形式 针对默认暴露
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>ES6 模块化</title>
</head>
<body>
   
    <script type="module">
        //1. 通用的导入方式
        //引入 m1.js 模块内容
        import * as m1 from "./src/js/m1.js";
        console.log(m1);
        console.log(m1.school); 
        m1.teach();
        //引入 m2.js 模块内容
        import * as m2 from "./src/js/m2.js";
        console.log(m2);
        console.log(m2.school); 
        m2.findJob();
        //引入 m3.js 
        import * as m3 from "./src/js/m3.js";
        console.log(m3);
        console.log(m3.default.school); 
        m3.default.change();
        //2. 解构赋值形式,可以直接使用变量和函数
        import {school, teach} from "./src/js/m1.js";
        console.log(school); 
        teach();
        import {school as guigu, findJob} from "./src/js/m2.js";
        console.log(guigu); 
        findJob();

        //解构赋值形式导入默认暴露的模块,必须给default进行别名设置
        import {default as m3_1} from "./src/js/m3.js";
        console.log(m3_1); 

        //3. 简便形式  针对默认暴露
        import m3_2 from "./src/js/m3.js";
        console.log(m3_2);
        
    </script>

</body>
</html>

模块化方式二

app.js

//入口文件

//模块引入
import * as m1 from "./m1.js";
import * as m2 from "./m2.js";
import * as m3 from "./m3.js";

// console.log(m1);
// console.log(m2);
// console.log(m3);

// m1.teach();
// m2.findJob();
// m3.default.change();

//修改背景颜色为粉色
import $ from 'jquery';// const $ = require("jquery");
$('body').css('background','pink');
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>ES6 模块化</title>
</head>
<body>
   <script src="./src/js/app.js" type="module"></script>

</body>
</html>

20、Babel对ES6模块化代码转换

Babel概述: Babel 是一个 JavaScript 编译器;
Babel 能够将新的ES规范语法转换成ES5的语法;
因为不是所有的浏览器都支持最新的ES规范,不能导入npm导入的模块,所以,一般项目中都需要使用Babel进行转换;
步骤:使用Babel转换JS代码——打包成一个文件——使用时引入即可;

步骤: 第一步:安装工具babel-cli(命令行工具) babel-preset-env(ES转换工具) browserify(打包工具, 项目中使用的是webpack);

第二步:初始化项目

npm init -yes

第三步:安装

npm i babel-cli babel-preset-env browserify -D

第四步:使用babel转换

src/js :(js目录);dist/js:(转化后的js目录)

npx babel src/js -d dist/js --presets=babel-preset-env

第五步:打包

npx browserify dist/js/app.js -o dist/bundle.js

第六步:在使用时引入bundle.js

<script src="./js/bundle.js" type="module"></script>

21、ES6模块化引入NPM包

演示: 第一步:安装jquery:

npm i jquery

第二步:在app.js使用jquery

//入口文件 
//修改背景颜色为粉色 
import $ from 'jquery';// 相当于const $ = require("jquery"); $('body').css('background','pink');

三、ES7 新特性

0、功能概述

1、Array.prototype.includes 判断数组中是否包含某元素,语法:arr.includes(元素值);

2、指数操作符 幂运算的简化写法,例如:2的10次方:2**10;

1、Array.prototype.includes

概述: Includes 方法用来检测数组中是否包含某个元素,返回布尔类型值; 判断数组中是否包含某元素,语法:arr.includes(元素值);

        // includes   indexOf
        const mingzhu = ['西游记', '红楼梦', '三国演义', '水浒传'];

        //判断
        console.log(mingzhu.includes('西游记'));//true
        console.log(mingzhu.includes('金瓶梅'));//false
        console.log(mingzhu.indexOf('西游记')); //0
        console.log(mingzhu.indexOf('金瓶梅'));//-1

2、指数操作符

概述: 在 ES7 中引入指数运算符「」,用来实现幂运算,功能与 Math.pow 结果相同; 幂运算的简化写法,例如:2的10次方:210;

代码实现:

        // **
        console.log(2 ** 10);// 1024
        console.log(Math.pow(2, 10));//1024

四、ES8 新特性

0、功能概述

1、async 和 await 简化异步函数的写法;

2、对象方法扩展 对象方法扩展;

1、async 和 await

概述: async 和 await 两种语法结合可以让异步代码看起来像同步代码一样; 简化异步函数的写法;

1)async 函数:

1.async 函数的返回值为 promise 对象; 2.promise 对象的结果由 async 函数执行的返回值决定;

//async 函数
async function fn() {
    // 返回一个字符串
    //return '尚硅谷';
    // 返回的结果不是一个 Promise 类型的对象, 返回的结果就是成功 Promise 对象
    // return;
    
    
    //抛出错误, 返回的结果是一个失败的 Promise
    // throw new Error('出错啦!');
    
    
    //返回的结果如果是一个 Promise 对象
    return new Promise((resolve, reject)=>{
        resolve('成功的数据');
        // reject("失败的错误");
     });
}

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

2)await 表达式:

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

//创建 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();

3)async 和 await 读取文件案例:

代码实现:

//1. 引入 fs 模块
const fs = require("fs");

//读取『为学』
function readWeiXue() {
    return new Promise((resolve, reject) => {
        fs.readFile("./resources/为学.md", (err, data) => {
            //如果失败
            if (err) reject(err);
            //如果成功
            resolve(data);
        })
    })
}

function readChaYangShi() {
    return new Promise((resolve, reject) => {
        fs.readFile("./resources/插秧诗.md", (err, data) => {
            //如果失败
            if (err) reject(err);
            //如果成功
            resolve(data);
        })
    })
}

function readGuanShu() {
    return new Promise((resolve, reject) => {
        fs.readFile("./resources/观书有感.md", (err, data) => {
            //如果失败
            if (err) reject(err);
            //如果成功
            resolve(data);
        })
    })
}

//声明一个 async 函数
async function main() {
    try {
        //获取为学内容
        let weixue = await readWeiXue();
        //获取插秧诗内容
        let chayang = await readChaYangShi();
        // 获取观书有感
        let guanshu = await readGuanShu();

        console.log(weixue.toString());
        console.log(chayang.toString());
        console.log(guanshu.toString());
    } catch (e) {
        console.log(e.message);
    }
}

main();

运行结果:

image-20220226213633008

没有nodejs 可以用下列代码测试

<!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 readWeiXue() {
            return new Promise((resolve, reject) => {
                setTimeout(() => {
                    resolve('1')
                }, 2000)
            })
        }

        function readChaYangShi(a) {
            return new Promise((resolve, reject) => {
                setTimeout(() => {
                    resolve('2')
                }, 2000)
            })
        }

        function readGuanShu(a) {
            return new Promise((resolve, reject) => {
                setTimeout(() => {
                    resolve('3')
                }, 2000)
            })
        }

        //声明一个 async 函数
        async function main() {
            try {
                //获取为学内容
                let weixue = await readWeiXue();
                //获取插秧诗内容
                console.log(111);
                let chayang = await readChaYangShi();
                // 获取观书有感
                console.log(2222);
                let guanshu = await readGuanShu();

                console.log(3333);
                console.log(weixue + chayang + guanshu);
            } catch (e) {
                console.log(e.message);
            }
        }

        main();
    </Script>
</body>

</html>

4)async 和 await 结合发送ajax请求:

代码实现:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>发送 AJAX 请求</title>
</head>

<body>
    <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 测试  
        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>
</body>

</html>

2、对象方法扩展

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

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>ES8 对象方法扩展</title>
</head>

<body>
    <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>
</body>

</html>

image-20220226220750786

五、ES9 新特性

0、功能概述

1、Rest 参数与 spread 扩展运算符

在对象中使Rest参数与spread扩展运算符; 2、正则扩展 简化和增强正则匹配;

1、Rest 参数与 spread 扩展运算符

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

代码实现:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>对象展开</title>
</head>

<body>
    <!-- 
        Rest 参数与 spread 扩展运算符在 ES6 中已经引入,不过 ES6 中只针对于数组,
        在 ES9 中为对象提供了像数组一样的 rest 参数和扩展运算符
     -->
    <script>
        //rest 参数
        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'
        });


        //对象合并
        const skillOne = {
            q: '天音波'
        }

        const skillTwo = {
            w: '金钟罩'
        }

        const skillThree = {
            e: '天雷破'
        }
        const skillFour = {
            r: '猛龙摆尾'
        }

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

        console.log(mangseng)

        // ...skillOne   =>  q: '天音波', w: '金钟罩'

    </script>

</body>

</html>

运行结果:

image-20220226221713911

2、正则扩展:命名捕获分组

概述: ES9 允许命名捕获组使用符号『?』,这样获取捕获结果可读性更强;

之前方法

        //声明一个字符串
        let str = '<a href="http://www.atguigu.com">尚硅谷</a>';

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

        // //执行
        const result = reg.exec(str);

        console.log(result);
        console.log(result[1]);
        console.log(result[2]);

image-20220226223428853

命名捕获分组

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>正则扩展-命名捕获分组</title>
</head>

<body>
    <script>
        //声明一个字符串
        // let str = '<a href="http://www.atguigu.com">尚硅谷</a>';

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

        // // //执行
        // const result = reg.exec(str);

        // console.log(result);
        // console.log(result[1]);
        // console.log(result[2]);


        let str = '<a href="http://www.atguigu.com">尚硅谷</a>';
        //分组命名
        const reg = /<a href="(?<url>.*)">(?<text>.*)<\/a>/;

        const result = reg.exec(str);

        console.log(result.groups.url);

        console.log(result.groups.text);
    </script>
</body>

</html>

image-20220226223545771

3、正则扩展:反向断言

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

代码实现:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>正则扩展-反向断言</title>
</head>

<body>
    <script>
        //声明字符串
        let str = 'JS5211314你知道么555啦啦啦';
        //正向断言
        const reg1 = /\d+(?=啦)/;
        const result1 = reg1.exec(str);
        console.log(result1);

        //反向断言
        const reg = /(?<=么)\d+/;
        const result = reg.exec(str);
        console.log(result);
    </script>
</body>

</html>

运行结果:

image-20220226224208031

4、正则扩展:dotAll 模式

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

代码实现:

exec迭代使用时,需要把正则设置为全局,否则一直匹配第一个

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>正则扩展-dotAll模式</title>
</head>

<body>
    <script>
        //dot  .  元字符  除换行符以外的任意单个字符
        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>\s+<a>(.*?)<\/a>\s+<p>(.*?)<\/p>/;
        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);


    </script>
</body>

</html>

运行结果:

image-20220226225354408

六、ES10 新特性

0、功能概述

1、Object.fromEntries 将二维数组或者map转换成对象; 2、trimStart 和 trimEnd 去除字符串前后的空白字符; 3、Array.prototype.flat 与 flatMap 将多维数组降维; 4、Symbol.prototype.description 获取Symbol的字符串描述;

1、Object.fromEntries

概述: 将二维数组或者map转换成对象; 之前学的Object.entries是将对象转换成二维数组;

代码实现:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Object.fromEntries</title>
</head>

<body>
    <script>
        //二维数组
        const result = Object.fromEntries([
            ['name', '尚硅谷'],
            ['xueke', 'Java,大数据,前端,云计算']
        ]);
        console.log(result);
        console.log('\r\n'); console.log('\r\n');


        //Map
        const m = new Map();
        m.set('name', 'ATGUIGU');
        const result1 = Object.fromEntries(m);
        console.log(m);
        console.log(result1);
        console.log('\r\n'); console.log('\r\n');


        //Object.entries ES8
        const arr = Object.entries({
            name: "尚硅谷"
        })
        console.log(arr);
        console.log(Object.fromEntries(arr));
    </script>
</body>

</html>

运行结果:

image-20220226230218490

2、trimStart 和 trimEnd

概述: 去掉字符串前后的空白字符;

代码实现:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>trimStart 与 trimEnd</title>
</head>

<body>
    <script>
        // trim
        let str = '   iloveyou   ';

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

</html>

运行结果:

image-20220226230419687

3、Array.prototype.flat 与 flatMap

概述: 将多维数组转换成低维数组;

代码实现:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>flat 与 flatMap</title>
</head>

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

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

</html>

运行结果:

image-20220226231205246

4、Symbol.prototype.description

概述: 获取Symbol的描述字符串;

代码实现:

//创建 Symbol
let s = Symbol('尚硅谷');

console.log(s.description);

运行结果:image-20220226231326059

七、ES11 新特性

0、功能概述

1、String.prototype.matchAll 用来得到正则批量匹配的结果; 2、类的私有属性 私有属性外部不可直接访问; 3、Promise.allSettled 获取多个promise执行的结果集; 4、可选链操作符 简化对象存在的判断逻辑; 5、动态 import 导入 动态导入模块,什么时候使用什么时候导入; 6、BigInt

大整型; 7、globalThis 对象 始终指向全局对象window;

1、String.prototype.matchAll

概述: 用来得到正则批量匹配的结果;

代码实现:

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <title>String.prototype.matchAll</title>
</head>

<body>
    <script>
        // String.prototype.matchAll 
        // 用来得到正则批量匹配的结果 
        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;
        var result = str.matchAll(reg);
        // 返回的是可迭代对象,可用扩展运算符展开 
        console.log([...result])

        console.log('\r\n\r\n');

        // 使用for...of...遍历 
        result = str.matchAll(reg);
        for (let v of result) { console.log(v); } 
    </script>
</body>

</html>

2、类的私有属性

概述: 私有属性外部不可直接访问;

代码实现:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>私有属性</title>
</head>

<body>
    <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('\r\n');
        // console.log(girl.#age);
        // console.log(girl.#weight);

        girl.intro();
    </script>
</body>

</html>

运行结果:

image-20220226233018079

3、Promise.allSettled

概述: 获取多个promise执行的结果集;

状态一定为成功fulfilled, 返回值为一个数组

数组每个元素都是一个对象,都有status属性

​ status 为"fulfilled" 另外一个属性value为成功的值

​ status 为"rejected"另外一个属性reason为失败的值

image-20220226234111619

代码实现:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Promise.allSettled</title>
</head>

<body>
    <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]);
        console.log(result);
        
        
         // Promise.all要求每个Promise都成功,
        	//成功后,成功的值是一个数组,每个元素对应各个Promise的成功值
        	// 否则为最先失败的值 
        // const res = Promise.all([p1, p2]);
        // console.log(res);

    </script>
</body>

</html>

4、可选链操作符

概述: 如果存在则往下走,省略对对象是否传入的层层判断;

代码实现:

       // ?.
        function main(config){
            // const dbHost = config && config.db && config.db.host;
            const dbHost = config?.db?.host;

            console.log(dbHost); //192.168.1.200 //若没有上传对应参数,这是undefined
        }

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

5、动态 import 导入

概述: 动态导入模块,什么时候使用时候导入;

import(url) 返回值是一个Promise对象,成功的值是模块暴露的对象

代码实现: hello.js:

export function hello(){
    alert('Hello');
}

app.js:

// import * as m1 from "./hello.js";
//获取元素
const btn = document.getElementById('btn');

btn.onclick = function(){
    import('./hello.js').then(module => {
        module.hello();
    });
}

动态import加载.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>动态 import </title>
</head>
<body>
    <button id="btn">点击</button>
    <script src="./js/app.js" type="module"></script>
</body>
</html>

运行结果:

image-20220227000400100

6、BigInt

概述: 更大的整数; 新的数据类型

代码实现:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>BigInt</title>
</head>

<body>
    <script>
        //大整形
        var n = 521n;
        console.log(n, typeof (n));

        //函数
        var n = 123;
        console.log(BigInt(n));

        // 不可以转化浮点数为BigInt,会报错
        // console.log(BigInt(1.2));

        //大数值运算BigInt 
        var max = Number.MAX_SAFE_INTEGER;
        console.log(max);
        console.log(max + 1);
        console.log(max + 2);
        console.log(max + 5 === max + 1);

        //BigInt 不可以与普通数值运算 需要转化
        console.log(BigInt(max))
        console.log(BigInt(max) + BigInt(1))
        console.log(BigInt(max) + BigInt(5))
    </script>
</body>

</html>

image-20220227000915894

7、globalThis 对象

概述: 始终指向全局对象window;

nodejs 的全局对象为global

console.log(globalThis);

image-20220227001415512

image-20220227001351995