Javascript ES6-11

ECMS相关介绍

什么是ECMA

ECMA(European Computer Manufacturers Association)中文名称为欧洲计算机制

造商协会,这个组织的目标是评估、开发和认可电信和计算机标准。1994 年后该

组织改名为 Ecma 国际

什么是ECMAScript

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

什么是ECMA-262

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

http://www.ecma-international.org/publications/standards/Standard.htm

ECMA-262历史版本

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

http://www.ecma-international.org/publications/standards/Ecma-262-arch.htm

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

谁在维护 ECMA-262

TC39(Technical Committee 39)是推进 ECMAScript 发展的委员会。其会员都是

公司(其中主要是浏览器厂商,有苹果、谷歌、微软、因特尔等)。TC39 定期

召开会议,会议由会员公司的代表与特邀专家出席

ES6兼容性

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

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

  • 兼容性

    http://kangax.github.io/compat-table/es6/

ECMAScript 6

let变量声明以及特性

- 声明对象类型使用 const,非对象类型声明选择 let

变量不能重复声明

//声明变量
        // let a;
        // let b,c,d;
        // let e = 100;
        // let f = 521, g = 'iloveyou', h = [];

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

块级作用域

  • 之前作用域: 全局, 函数, eval(eveal,es5严格模式才出现)
  • 现在引入块级作用域if else while for 都是块级作用域
 // if else while for 都是块级作用域
           {
                  girl = '周扬青';
           }
           console.log(girl);
        //girl is not defined

### 不存在变量提升

		console.log(song);
        let song = '恋爱达人';
 // Cannot access 'song' before initialization

不影响作用域链

 {
            let school = 'wangkai';
            function fn(){
                console.log(school);
            }
            fn();  //wangkai
        }

const声明常量以及特点

  • 值不能修改的量叫常量

  • 声明常量

     const SCHOOL = '你好啊';
            console.log(SCHOOL)  //你好啊
    

一定要赋初始值

 const A;
        //Missing initializer in const declaration

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

onst a = 100;

常量的值不能修改

 const SCHOOL = '你好啊';
        SCHOOL = 'ABCD';
        // console.log(SCHOOL)  //Assignment to constant variable.

块级作用域

 {
            const PLAYER = 'UZI';
        }
        console.log(PLAYER);
        //PLAYER is not defined

改对象不会报错

  • 对于数组和对象的元素修改, 不算做对常量的修改, 不会报错
  const TEAM = ['UZI','MXLG','Ming','Letme'];
        // TEAM.push('Meiko');

变量的解构赋值

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

数组的解构

 const F4 = ['小沈阳','刘能','赵四','宋小宝'];
        let [xiao, liu, zhao, song] = F4;
        console.log(xiao); //小沈阳
        console.log(liu); //刘能
        console.log(zhao); //赵四
        console.log(song); //宋小宝

### 对象的解构

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

        let {name, age, xiaopin} = zhao;
        console.log(name); //赵本山
        console.log(age);  //不详
        console.log(xiaopin); 
        //ƒ (){ console.log("我可以演小品");}

        // xiaopin(); //我可以演小品

        // 以前:zhao.xiaopin();
        //     zhao.xiaopin();
        //     zhao.xiaopin();
        //     zhao.xiaopin(); //我可以演小品

        // 现在:
        let {xiaopin} = zhao;  //我可以演小品
        xiaopin();

模板字符串

``

  • ES6引入了新的声明方式``
  • 以前: ''" "
let str = `我也是一个字符串哦!`;
console.log(str, typeof str);

内容中可以直接出现换行

let str = `<ul>
                    <li>沈腾</li>
                    <li>玛丽</li>
                    <li>魏翔</li>
                    <li>艾伦</li>
                    </ul>`;
        console.log(str)
                     // <ul>
                     //<li>沈腾</li>
                     //<li>玛丽</li>
                     //<li>魏翔</li>
                     //<li>艾伦</li>
                     //</ul>

变量拼接

let lovest = '魏翔';
        let M = '呵呵呵'
        let out = `${lovest}是我心目中最搞笑的演员${M}!!`;
        console.log(out);
        // 魏翔是我心目中最搞笑的演员呵呵呵!!

简化对象写法

  • ES6 允许在大括号里面,直接写入变量和函数,作为对象的属性和方法。这样的书写更加简洁
 let name = '尚硅谷';
        let change = function(){
            console.log('我们可以改变你!!');
        }

        const school = {
            name,  //属性名和变量名一样可以省略一个
            change,
            improve(){    //省略了function和:
                console.log("我们可以提高你的技能");
            }
        }

        console.log(school);
        //{name: "尚硅谷", change: ƒ, improve: ƒ}

箭头函数

声明一个箭头函数

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

        // }    //以前

        let fn = (a,b) => {
            return a + b;
        }

        //调用函数
        let result = fn(1, 2);
        console.log(result);  //3

箭头函数的this

箭头函数适合与 this 无关的回调.

比如 :定时器, 数组的方法回调

头函数不适合与 this 有关的回调(只是说不适合)

事件回调, 对象的方法

  • this 是静态的. 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);   //ATGUIGU  改变
        getName2.call(school);  //尚硅谷    箭头函数this静态的,不会变

不能作为构造实例化对象

let Person = (name, age) => {
            this.name = name;
            this.age = age;
        }
        let me = new Person('xiao',30);
        console.log(me);
        //Person is not a constructor

### 不能使用arguments变量

 let fn = () => {
            console.log(arguments);
        }
        fn(1,2,3);//arguments is not defined

省略小括号

  • 当形参有且只有一个的时候,可以省略小括号
let add = n => {
                return n + n;
            }
            console.log(add(9)); //18

省略花括号

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

实践

  • 需求-1 点击 div 2s 后颜色变成『粉色』
//需求-1  点击 div 2s 后颜色变成『粉色』
        //获取元素
        let ad = document.getElementById('ad');
        //绑定事件
        ad.addEventListener("click", function(){
            //以前保存 this 的值
            // let _this = this;  

            //定时器
            setTimeout(() => {   //之前是function,现在是箭头函数
                //修改背景颜色 this
                // console.log(this);  //window
                //this找不到就像外层找,保存外部的this
                // _this.style.background = 'pink';
                this.style.background = 'pink';
                //现在this指向外层作用域,外层的this指向ad
            }, 2000);
        });
  • 从数组中返回偶数的元素
  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); //(3) [6, 10, 100]

允许设置参数默认值

形参初始值

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

与解构赋值结合

 function connect({host="127.0.0.1", username,password, port}){
            console.log(host) //atguigu.com
            console.log(username) //root
            console.log(password) //root
            console.log(port) //3306
        }
        connect({
            host: 'atguigu.com',
            username: 'root',
            password: 'root',
            port: 3306
        })

rest参数

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

ES5 获取实参的方式

  • 返回的是对象
 function date(){
            console.log(arguments);
        }
        date('白芷','阿娇','思慧');
        // Arguments(3) ["白芷", "阿娇", "思慧", callee: ƒ, Symbol(Symbol.iterator): ƒ]

rest 参数

  • 返回的是数组,可以对数组用下面方法
  • 可以用数组的方法…filter some every map

        function date(...args){
            console.log(args);
            //(3) ["阿娇", "柏芝", "思慧"] 
            //返回的是数组,可以对数组用下面方法
            // filter some every map 
        }

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

function fn(a,b,...args){
            console.log(a);
            console.log(b);
            console.log(args);
        }
        fn(1,2,3,4,5,6); //1,2  (4) [3, 4, 5, 6]

spread扩展运算符

…扩展元素运算符

  • ...扩展运算符能将数组转换成为逗号分隔的参数序列
const tfboys = ['易烊千玺','王源','王俊凯'];
        // => '易烊千玺','王源','王俊凯'

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

        chunwan(...tfboys);// chunwan('易烊千玺','王源','王俊凯')
        //rest ...是放在了形参,而这个是实参

------扩展运算符的应用------

数组的合并

const kuaizi = ['王太利','肖央'];
        const fenghuang = ['曾毅','玲花'];

        // const zuixuanxiaopingguo = kuaizi.concat(fenghuang);  //以前方法
        //(4) ["王太利", "肖央", "曾毅", "玲花"]

        const zuixuanxiaopingguo = [...kuaizi, ...fenghuang];
        console.log(zuixuanxiaopingguo);
        // //(4) ["王太利", "肖央", "曾毅", "玲花"]

数组的克隆

  • 是一个浅拷贝
  const sanzhihua = ['E','G','M'];
        const sanyecao = [...sanzhihua];
        console.log(sanyecao);//  ['E','G','M']

### 将伪数组转为真正的数组

const divs = document.querySelectorAll('div');
        console.log(divs);
        // __proto__(Nodelist).__proto__ (Object)

        const divArr = [...divs];
        console.log(divArr);
        //__proto__(Array).__proto__ (Object)

Symbol

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

symbol特点

  • Symbol 的值是唯一的,用来解决命名冲突的问题
  • Symbol 值不能与其他数据进行运算

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

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

创建Symbol

let s = Symbol();   //函数
        console.log(s, typeof s);
        //Symbol() "symbol"

Symbol唯一性

let s2 = Symbol('尚硅谷');
        let s3 = Symbol('尚硅谷');
        // console.log(s2 === s3)   //false

Symbol.for创建

 let s4 = Symbol.for('尚硅谷');  //函数对象
        let s5 = Symbol.for('尚硅谷');
        console.log(s4,typeof s4) 
        //Symbol(尚硅谷) "symbol"
        // console.log(s4 === s5)   //true

不能与其他数据进行运算

 let result = s + 100;
           let result = s > 100;
           let result = s + s;
//Identifier 'result' has already been declared

七种数据类型

USONB  you are so niubility 
        u  undefined
        s  string  symbol
        o  object
        n  null number
        b  boolean

------❥给对象添加Symbol属性的两种方式❥------

Symbol作用 给对象添加属性和方法(独一无二)

第一种

 //向对象中添加方法 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);
 //{name: "俄罗斯方块", up: ƒ, down: ƒ, Symbol(): ƒ, Symbol(): ƒ}

第二种

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

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

------❥Symbol内置属性❥------

Symbol.hasInstance

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

        let o = {};

        console.log(o instanceof Person);
        // {}
        //我被用来检测类型了
        //false

Symbol.isConcatSpreadable

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

Iterator 迭代器

  • 需要自定义遍历数据的时候,要想到迭代器。

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

  • Iterator接口 就是对象里的一个属性,这个属性的名字叫做[Symbol.iterator]

  • ES6 创造了一种新的遍历命令 for…of 循环,Iterator 接口主要供 for…of 消费

  • 原生具备 iterator 接口的数据(可用 for of 遍历)

    1. Array
    2. Arguments
    3. Set
    4. Map
    5. String
    6. TypedArray
    7. NodeList

for…of 遍历数组

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


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

        console.log(xiyou)
//[(4) ["唐僧", "孙悟空", "猪八戒", "沙僧"].__proto__
//Symbol(Symbol.iterator): ƒ values()]

迭代器工作原理

  1. 创建一个指针对象,指向当前数据结构的起始位置
  2. 第一次调用对象的 next 方法,指针自动指向数据结构的第一个成员
  3. 接下来不断调用 next 方法,指针一直往后移动,直到指向最后一个成员
  4. 每调用 next 方法返回一个包含 value 和 done 属性的对象
 const xiyou = ['唐僧','孙悟空','猪八戒','沙僧'];
        let iterator = xiyou[Symbol.iterator]();
        // console.log(iterator)
        //Array Iterator {}.__proto__
        //next: ƒ next()

        //调用对象的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} true表示遍历循环完成

自定义迭代器遍历对象

 //声明一个对象
        const banji = {
            name: "终极一班",
            stus: [
                'xiaoming',
                'xiaoning',
                'xiaotian',
                'knight'
            ],
            // 加上Iterator接口(方法)
            [Symbol.iterator]() {
                //索引变量
                let index = 0;
                //
                let _this = this;
                //返回一个对象(对应1.创建一个指针对象,指向当前数据结构的起始位置)
                return {
                    //添加next方法(对应4.每调用 next 方法返回一个包含 value 和 done 属性的对象)
                    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); //xiaoming,xiaoning,xiaotian,knight
        }

生成器函数

  • 生成器函数是 ES6 提供的一种异步编程解决方案

生成器本身是一个函数

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

生成器其实就是一个特殊的函数(声明特殊,执行特殊,调next方法才运行)

异步编程 纯回调函数 node fs ajax mongodb

yield算作函数代码的分隔符

生成器函数的声明

  • 代码说明
    • * 的位置没有限制
    • 生成器函数返回的结果是迭代器对象,调用迭代器对象的 next 方法可以得到yield 语句后的值
    • yield 相当于函数的暂停标记,也可以认为是函数的分隔符,每调用一次 next方法,执行一段代码
    • next 方法可以传递实参,作为 yield 语句的返回值
function * gen(){
            console.log(111);
            yield '一只没有耳朵'; 
                       //(yield后面跟表达式或者跟字面量)
            console.log(222);
            yield '一只没有尾部';
            console.log(333);
            yield '真奇怪';
            console.log(444);
        }

        // let iterator = gen();
        // iterator.next(); //111
        // iterator.next(); //222
        // iterator.next(); //333
        // iterator.next(); //444

        // console.log(iterator.next());
        // 111
        //{value: "一只没有耳朵", done: false}
        // console.log(iterator.next());
        //222
        //{value: "一只没有尾部", done: false}
        // console.log(iterator.next());
        //333
        //{value: "真奇怪", done: false}
        // console.log(iterator.next());
        //444
        //{value: undefined, done: true}
        


        //遍历
        for(let v of gen()){
            console.log(v);
        }
        //111
        //一只没有耳朵
        //222
        //一只没有尾部
        //333
        //真奇怪
        //444

### 生成器函数的调用

function * gen() {
            yield 111;
            yield 222;
            yield 333;
        }

        //执行获取迭代器对象
        let iterator = gen();
        console.log(iterator.next())
        //{value: 111, done: false}
         console.log(iterator.next())
        //{value: 222, done: false}
         console.log(iterator.next())
        //{value: 333, done: false}
         console.log(iterator.next())
        //{value: undefined, done: true}

生成器函数传参

  • 生成器整体函数传参
  • next方法也是可以传参的(实参),而且我们这个方法(实参)作为上一个yield语句的返回结果
  • 第二次调用next,yield传入的参数作为第一个yield语句整体返回结果
function * gen(arg) {
            console.log(arg)  //undefined
            let one = yield 111;
            console.log(one) //BBB

            let two = yield 222;
            console.log(two)//CCC

            let three = yield 333;
            console.log(three)//DDD
        }

        let iterator = gen()  //undefined
        console.log(iterator.next('kkk')) 
        //经过测试,第一次传参无用 
        //{value: 111, done: false}
        console.log(iterator.next('BBB'))  
        //{value: 222, done: false}
        console.log(iterator.next('CCC')) 
         //{value: 333, done: false}
        console.log(iterator.next('DDD'))  
        //{value: undefined, done: true}

回调地狱

异步编程:比如: 1.文件操作 2.网络操作(ajax, request) 3.数据库操作

  • 需求:1s后控制台输出 111 2s后输出 222 3s后输出 333
setTimeout(() => {
            console.log(111);
            setTimeout(() => {
                console.log(222);
                setTimeout(() => {
                    console.log(333);
                }, 3000);
            }, 2000);
        }, 1000);

生成器函数解决回调地狱

需求: 1s后控制台输出 111 2s后输出 222 3s后输出 333

  • 生成器函数解决
    • 声明三个函数.分别完成三个异步任务
 //输出1任务
        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(); 
        // 不在任务重加iterator.next()只输出111
        //111/222/333

生成器函数在异步任务的表现

  • 模拟获取 用户数据 订单数据 商品数据
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();  
                console.log(users) //用户数据
            let orders = yield getOrders();
                console.log(orders) //订单数据
            let goods = yield getGoods();
                console.log(goods) //商品数据
        }

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

Promise

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

实例化Promise对象

  • 成功状态
const p = new Promise(function(resolve,reject) {
            setTimeout(function() {
                let data = '数据库中的用户数据';
                // 调用resovle方法
                resolve(data)
//调用resolve函数以后,这个Promise对象状态就会变为成功
//对象有三个状态: 初始化 成功  失败
            },1000);
        });
        
        //调用promise对象的then方法
        //成功的形参叫value,失败的形参叫reason
        p.then(function(value){
            console.log(value); //数据库中的数据
        },function(){

        })

  • 失败状态
const p = new Promise(function(resolve,reject) {
            setTimeout(function() {
                let data = '数据库中的用户数据';
                // 调用resovle方法
                reject(data)
//调用resolve函数以后,这个Promise对象状态就会变为成功
//对象有三个状态: 初始化 成功  失败
            },1000);
        });
        
        //调用promise对象的then方法
        //成功的形参叫value,失败的形参叫reason
        p.then(function(value){
            console.log(value); //数据库中的数据
        },function(reason){
            console.error(reason); //数据库中的用户数据
        })

Promise封装读取文件

  • 调用方法读取文件
//1. 引入 fs 模块
const fs = require('fs');

fs.readFile('./resources/为学.md', (err, data)=>{
    //如果失败, 则抛出错误
    if(err) throw err;
    //如果没有出错, 则输出内容
    // console.log(data);  //buffer
    console.log(data.toString()); //一首诗
});
  • 使用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("读取失败!!");
});

Promise封装AJAX

  • 发送ajax请求
<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/getJok(e)");

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

            //4. 绑定事件, 处理响应结果
            xhr.onreadystatechange = function () {
                //判断
                if (xhr.readyState === 4) {
                    //判断响应状态码 200-299
                    if (xhr.status >= 200 && xhr.status < 300) {
                        //表示成功
                        // console.log(xhr.response);  文本
                        resolve(xhr.response);
                    } else {
                        //如果失败
                        // console.error(xhr.status);  404  
                        reject(xhr.status);
                    }
                }
            }
        })
        
        //指定回调
        p.then(function(value){
            console.log(value);
        }, function(reason){
            console.error(reason);
        });
    </script>

Promise.prototype.then

<script>
        //创建 promise 对象
        const p = new Promise((resolve, reject)=>{
            setTimeout(()=>{
                resolve('用户数据');
                // reject('出错啦');
            }, 1000)
        });
        // 调用then方法
        const result = p.then(value => {
            console.log(value);
            return '王凯';
        },reason => {
            console.warn(reason);
        })

        console.log(result)

        //Promise {<pending>}
        // __proto__: Promise
        //[[PromiseStatus]]: "fulfilled"
        //[[PromiseValue]]: undefined

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

        // const result = p.then(value => {
        //     console.log(value);
        //     //1. 非 promise 类型的属性
        //     // return 'iloveyou';

        //     //2. 是 promise 对象
        //     // return new Promise((resolve, reject)=>{
        //     //     // resolve('ok');  then方法就chegng,返回值then成功的值
        //     //     reject('error');  //then方法就失败,返回的值就是then方法的值
        //     // });

        //     //3. 抛出错误
        //     // throw new Error('出错啦!');
        //     throw '出错啦!';
        // }, reason=>{
        //     console.warn(reason);
        // });

        //链式调用 then方法可以返回一个promise对象,所以可以链式调用
        // p.then(value=>{

        // }).then(value=>{

        // });


    </script>

实践–读取多个文件

//引入 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'));   //三首诗
});

Promise-catch方法

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

Set 集合

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

### new Set()

  • 声明set
 let s = new Set();
            console.log(s,typeof s)
            //Set(0) "object"

set会自动去重

 s2 = new Set(['大事儿','小事儿','好事儿','坏事儿','小事儿']);
            console.log(s2)
            //它会自动去重
            //Set(4) {"大事儿", "小事儿", "好事儿", "坏事儿"}

.size

  • 元素的个数
    • 返回集合的元素个数

        console.log(s2.size); 
        //4

.add()

  • 添加元素
    • 增加一个新元素,返回当前集合
 s2.add('喜事儿');
        console.log(s2)
        //Set(5) {"大事儿", "小事儿", "好事儿", "坏事儿", "喜事儿"}

.delete()

  • 删除元素
    • 删除元素,返回boolean值
s2.delete('坏事儿');
        console.log(s2)
        //Set(4) {"大事儿", "小事儿", "好事儿", "喜事儿"}

.has()

  • 检测
    • 检测集合中是否包含某个元素,返回 boolean 值
  console.log(s2.has('糟心事'));
        // false

.clear()

  • 清空
    • 清空集合,返回 undefined
 // s2.clear();
        // console.log(s2);
        //Set(0) {}

for…of

for(let v of s2){
            console.log(v);
        }
        //大事儿, 小事儿, 好事儿, 喜事儿
        

❥集合实践❥(

数组去重

 let arr = [1,2,3,4,5,4,3,2,1];
        let result = [...new Set(arr)];
        console.log(result);
        //(5) [1, 2, 3, 4, 5]

交集

let arr = [1,2,3,4,5,4,3,2,1];
        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;
            }
        });
        // console.log(result)  //(2) [4, 5]
 let arr = [1,2,3,4,5,4,3,2,1];
        let arr2 = [4,5,6,5,6];
        let result = [...new Set(arr)].filter(item => new Set(arr2).has(item));
        // console.log(result);   // 4 5

并集

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

        let union = [...new Set([...arr, ...arr2])];
        console.log(union);
        //[1, 2, 3, 4, 5, 6]

差集(和交集相反)

  let arr = [1,2,3,4,5,4,3,2,1];
        let arr2 = [4,5,6,5,6];
        let diff = [...new Set(arr)].filter(item => !(new Set(arr2).has(item)));
        console.log(diff);
        //(3) [1, 2, 3]

Map

  • 升级版的对象

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

new Map()

  • 声明Map
 let m = new Map();
        console.log(m)
        //Map(0) {}

.set()

  • 增加一个新元素,返回当前 Map
 m.set('name','尚硅谷');
        console.log(m)
        //Map(1) {"name" => "尚硅谷"}
        //key: "name"
        //value: "尚硅谷"
 m.set('change', function(){
            console.log("我们可以改变你!!");
        });
        //{"change" => function(){ console.log("我们可以改变你!!"); }}
        //key: "change"
let key = {
            school : 'ATGUIGU'
        };
        m.set(key, ['北京','上海','深圳']);
        //key: {school: "ATGUIGU"}
        //value: (3) ["北京", "上海", "深圳"]

.size

  • 返回Map的元素个数
  console.log(m.size);
        //3

.delte()

  • 删除
m.delete('name');
        console.log(m)
        //Map(2) {"change" => ƒ, {…} => Array(3)}

.get()

  • 返回键名对象的键值
console.log(m.get('change'));
        //ƒ (){
            //console.log("我们可以改变你!!");
        //}
console.log(m.get(key));
        //(3) ["北京", "上海", "深圳"]

.has()

  • 检测 Map 中是否包含某个元素,返回 boolean 值

.clear()

  • 清空集合,返回 undefined
 m.clear();
        //Map(0){}

for…of

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

        // console.log(m);
        //(2) ["name", "尚硅谷"]
        //Map.html:65 (2) ["change", ƒ]
        //Map.html:65 (2) [{…}, Array(3)]

class 类

  • class 声明类
  • constructor 定义构造函数初始化
  • extends 继承父类
  • super 调用父级构造方法
  • static 定义静态方法和属性
  • 父类方法可以重写

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

  • ES5实例化对象
 //ES5 实例化对象
        //手机  实例对象的属性初始化
        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);
        //Phone   brand: "华为"    price: 5999  __proto__: Object

声明class

  • 构造方法 名字不能修改 必须叫constructor
    • 使用new加类型的时候,会自动执行实例对象上的constructor方法
  • 方法必须使用该语法, 不能使用 ES5 的对象完整形式
    • 方法名+()+{} 没有function 和 :
 class Shouji{
            //构造方法 名字不能修改  必须叫constructor
            //使用new加类型的时候,会自动执行实例对象上的constructor方法
            constructor(brand, price){
                this.brand = brand;
                this.price = price;
            }

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

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

        console.log(onePlus);
        //Shouji {brand: "1+", price: 1999}  brand: "1+"  price: 1999  __proto__: Object
        

static 类的静态成员

  • 静态属性
  • static标注的属性和方法它属于类而不属于实例对象
class Phone{
            //静态属性
            //static标注的属性和方法它属于类而不属于实例对象
            static name = '手机';
            static change(){
                console.log("我可以改变世界");
            }
        }

        let nokia = new Phone();
        console.log(nokia.name); //undefined
        console.log(Phone.name); //手机
  • ES5里面
    • 实例对象是实例对象 函数对象是函数对象 他们的属性是不通的
    • 实力对象里面的属性 和函数对象里面的属性是不通的
 function Phone(){

        }
        Phone.name = '手机';
        Phone.change = function(){
            console.log("我可以改变世界");
        }
        //上面这些属性属于函数对象的,并不属于实例对象 称为静态成员


        Phone.prototype.size = '5.5inch';

        let nokia = new Phone();
        console.log(nokia.name);
        //undefined

        nokia.change();
        console.log(nokia.size);
        //nokia.change is not a function

        console.log(nokia.size)
        //5.5inch

ES5类继承

 //手机
        function Phone(brand, price){
            this.brand = brand;
            this.price = price;
        }

        Phone.prototype.call = function(){
            console.log("我可以打电话");
        }


        //智能手机
        function SmartPhone(brand, price, color, size){
            Phone.call(this, brand, price);
            //this指向SmartPhone里面的this,也就是SmartPhone实例化对象
            this.color = color;
            this.size = size;
        }

        //为了实现继承 设置子级构造函数的原型
        SmartPhone.prototype = new Phone;
        // 不加也行
        SmartPhone.prototype.constructor = SmartPhone;

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

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

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

        console.log(chuizi);

extends 继承父类

  • extends 继承父类
 <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>

子类是不能调用父类的同名方法的

<script>
        //js语法里子类是不能调用父类的同名方法的
        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>

class的set 和 get

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

数值扩展

Number.EPSILON

  • Number.EPSILON 是 JavaScript 表示的最小精度
  • EPSILON 属性的值接近于 2.2204460492503130808472633361816E-16
function equal(a, b){
            if(Math.abs(a-b) < Number.EPSILON){
                return true;
            }else{
                return false;
            }
        }
        // console.log(0.1 + 0.2 === 0.3);  false
        // console.log(equal(0.1 + 0.2, 0.3)) //true

0b 0o

  • ES6 提供了二进制和八进制数值的新的写法,分别用前缀 0b 和 0o 表示。
 //1. 二进制和八进制
        let b = 0b1010;  //10
        let o = 0o777;  //511
        let d = 100;  //100
        let x = 0xff; //255
        // console.log(x);

Number.isFinite()

  • 用来检查一个数值是否为有限数
nsole.log(Number.isFinite(100));   //true
        console.log(Number.isFinite(100/0));  //false
        console.log(Number.isFinite(Infinity));  //false

Number.isNaN()

  • 用来检查一个值是否为 NaN
console.log(Number.isNaN(123));    //false

Number.parseInt()

  • ES6 将全局方法 parseInt 和 parseFloat,移植到 Number 对象上面,使用不变。
console.log(Number.parseInt('5211314love'));  //5211314

Number.parseFloat()

console.log(Number.parseFloat('3.1415926神奇'));  //3.1415926

Math.trunc()

  • 用于去除一个数的小数部分,返回整数部分。
console.log(Math.trunc(3.5)); //3

Number.isInteger()

  • 用来判断一个数值是否为整数
console.log(Number.isInteger(5));  //true
        console.log(Number.isInteger(2.5));  //false

Math.sign()

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

对象方法扩展

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

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

Object.is

  • 判断两个值是否完全相等
 console.log(Object.is(120, 120));// 类似于=== true
        console.log(Object.is(NaN, NaN));// 区别=== true
        console.log(NaN === NaN);// === //false

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));
 //{host: "http://atguigu.com", port: 33060, name: "atguigu.com", pass: "iloveyou", test: "test", …}

Object.setPrototypeOf

  • 设置原型对象,并不建议这样去做
 const school = {
            name: '尚硅谷'
        }
        const cities = {
            xiaoqu: ['北京','上海','深圳']
        }
        Object.setPrototypeOf(school, cities);
        console.log(Object.getPrototypeOf(school));

        console.log(school);//{xiaoqu: Array(3)}
  • Object.getPrototypeof

模块化

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

模块化的好处

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

模块化规范产品

  • ES6之前的模块化规范有
CommonJSNodeJS、Browserify
AMDrequireJS
CMDseaJS

使用ES6模块化引入模块

❥通用的导入方式❥

  • 浏览器使用ES6模块化引入模块
  <script type="module">
        //引入wk.js模块内容
        import * as wk from './wk.js'
        console.log(wk);
    </script>

export 分别暴露

export let name = 'wangkai';
export function home() {
    console.log('万科欢迎您');
}
<script type="module">
        //引入wk.js模块内容
        import * as wk from './wk.js'
        console.log(wk);
        wk.default.home()  //万科欢迎您
    </script>

export{} 统一暴露

let name = 'wangkai';
function home() {
    console.log('万科欢迎您');
}

export{name,home}
<script type="module">
        //引入wk.js模块内容
        import * as wk from './wk.js'
        console.log(wk);
        wk.default.home()  //万科欢迎您
    </script>

export default{} 默认暴露

  • 花括号里面可以使任意类型 值
  • 调用方法需要将加default : xxx.default.xxx()
export default{
     name : 'wangkai',
    home:function() {
       console.log('万科欢迎您');
   }
 }
 <script type="module">
        //引入wk.js模块内容
        import * as wk from './wk.js'
        console.log(wk);
        wk.default.home()  //万科欢迎您
    </script>

### ❥解构赋值形式引入❥

export 分别暴露

import {name,home} from './wk.js';

// console.log(name);  //wangkai
// console.log(home);  //ƒ home() {  console.log('万科欢迎您');}
export let name = 'wangkai';
export function home() {
    console.log('万科欢迎您');
}

export{} 统一暴露

  • Identifier ‘name’ has already been declared
  • 使用as 加别名,就不会和上面name冲突
 import {name as namee,house} from './wkk.js';
 
 // console.log(name);  //wangkai
// console.log(home);  //ƒ home() {  console.log('万科欢迎您');}
let name = 'wangkai';
function home() {
    console.log('万科欢迎您');
}

export{name,home}

export default{} 默认暴露

//default必须使用别名
        import {default as kgg} from './wkkk.js';
        console.log(kgg);  //{name: "wangkai", home: ƒ}
        
// console.log(name);  //wangkai
// console.log(home);  //ƒ home() {  console.log('万科欢迎您');} 
  • 花括号里面可以使任意类型 值
  • 调用方法需要将加default : xxx.default.xxx()
export default{
     name : 'wangkai',
    home:function() {
       console.log('万科欢迎您');
   }
 }

简便形式,只能针对默认形式

 import wkkk from './wkkk.js';
        console.log(wkkk); //{name: "wangkai", home: ƒ}

单独创建一个文档

  • html
<script src="./app.js" type="module"></script>
  • js
// 入口文件

// 模块引入
import * as wk from './wk.js';
import * as wkk from './wkk.js';
import * as wkkk from './wkkk.js';
console.log(wk);
console.log(wkk);
console.log(wkkk);

ES6-ES6模块化引入NPM包

<!-- 
        1. 安装工具 npm i babel-cli babel-preset-env browserify(webpack) -D
        2. 编译 npx babel src/js -d dist/js --presets=babel-preset-env
        3. 打包 npx browserify dist/js/app.js -o dist/bundle.js
     -->
//修改背景颜色为粉色
import $ from 'jquery';// const $ = require("jquery");
$('body').css('background','pink');

ECMAScript7

.includes

  • Array.prototype.includes
  • Includes 方法用来检测数组中是否包含某个元素,返回布尔类型值
// includes   indexOf(以前用indexOf)
        const mingzhu = ['西游记','红楼梦','三国演义','水浒传'];

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

** 幂运算符

  • 在 ES7 中引入指数运算符「**」,用来实现幂运算,功能与 Math.pow 结果相同
 console.log(2 ** 10);// 1024
        //效果一样的  **更简单
        console.log(Math.pow(2, 10));//1024

ECMAScript8

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

async 函数

  • async用来声明一个特殊的函数
  • async 函数的返回值为 promise 对象,
  • promise 对象的结果由 async 函数执行的返回值决定
<script>
        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>

await 表达式

  • await 必须写在 async 函数中
  • await 右侧的表达式一般为 promise 对象
  • await 返回的是 promise 成功的值
  • await 的 promise 失败了, 就会抛出异常, 需要通过 try…catch 捕获处理
//创建 promise 对象
        const p = new Promise((resolve, reject) => {
            // resolve("用户数据");
            reject("失败啦!");
        })



        // await 要放在 async 函数中.
        async function main() {
           // let result =  await p;
           // console.log(result)  //用户数据
            try {
                let result = await p; //用户数据
                //
                console.log(result);
            } catch (e) {
                console.log(e);  //失败啦!
            }
        }
        //调用函数
        main();

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(){
    //获取为学内容
    let weixue = await readWeiXue();
    //获取插秧诗内容
    let chayang = await readChaYangShi();
    // 获取观书有感
    let guanshu = await readGuanShu();

    console.log(weixue.toString());
    console.log(chayang.toString());
    console.log(guanshu.toString());
}

main();

async和await封装AJAX请求

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

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

        //获取对象所有的键
        console.log(Object.keys(school));
        //0: "name"1: "cities"2: "xueke"

Object.values

  • Object.values()方法返回一个给定对象的所有可枚举属性值的数组
//获取对象所有的值
        // console.log(Object.values(school));
        //["尚硅谷", Array(3), Array(4)]

Object.entries

  • Object.entries()方法返回一个给定对象自身可遍历属性 [key,value] 的数组
 console.log(Object.entries(school));
        // (3) [Array(2), Array(2), Array(2)]
        // 0: (2) ["name", "尚硅谷"]
        // 1: (2) ["cities", Array(3)]
        // 2: (2) ["xueke", Array(4)]
//创建 Map
        // const m = new Map(Object.entries(school));
        // console.log(m.get('cities'));

Object.getOwnPropertyDescriptors

  • Object.getOwnPropertyDescriptors
  • 该方法返回指定对象所有自身属性的描述对象
 //对象属性的描述对象
        console.log(Object.getOwnPropertyDescriptors(school));
        //{name: {…}, cities: {…}, xueke: {…}}

        // const obj = Object.create(null, {
        //     name: {
        //         //设置值
        //         value: '尚硅谷',
        //         //属性特性
        //         writable: true,
        //         configurable: true,
        //         enumerable: true
        //     } 
        // });

ECMAScript9

Rest/Spread属性

  • Rest 参数与 spread 扩展运算符在 ES6 中已经引入,不过 ES6 中只针对于数组,在 ES9 中为对象提供了像数组一样的 rest 参数和扩展运算符
//rest 参数
        function connect({host, port, ...user}){
            console.log(host);  //127.0.0.1
            console.log(port);  //3306
            console.log(user);  //{username: "root", password: "root", type: "master"}
        }

        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)
        //{q: "天音波", w: "金钟罩", e: "天雷破", r: "猛龙摆尾"}

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

正则命名分组

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);
        //http://www.atguigu.com
        console.log(result.groups.text);
        //尚硅谷
  • 以前办法
 //声明一个字符串
        let str = '<a href="http://www.atguigu.com">尚硅谷</a>';

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

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

        console.log(result);  
        //["<a href="http://www.atguigu.com">尚硅谷</a>", "http://www.atguigu.com", "尚硅谷", index: 0, input: "<a href="http://www.atguigu.com">尚硅谷</a>", groups: undefined]

        console.log(result[1]);
        //http://www.atguigu.com
        console.log(result[2]);
        // 尚硅谷

正则 正向断言

 //声明字符串
        let str = 'JS5211314你知道么555啦啦啦';
        //正向断言
        const reg = /\d+(?=啦)/;
        const result = reg.exec(str); 
        console.log(result)
        //["555", index: 13, input: "JS5211314你知道么555啦啦啦", groups: undefined]

正则 反向断言

 //反向断言
        const reg = /(?<=么)\d+/;
        const result = reg.exec(str);
        console.log(result);
         //["555", index: 13, input: "JS5211314你知道么555啦啦啦", groups: undefined]

. dotAll模式

  • dot . 元字符 除换行符以外的任意单个字符

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

    终止符出现

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);

ECMAScript10

Object.fromEntries

  • Object.entries和它相反

  • 二维数组

const result = Object.fromEntries([
            ['name','尚硅谷'],
            ['xueke', 'Java,大数据,前端,云计算']
        ]);
        console.log(result)
        //Object
        //name: "尚硅谷"
        //xueke: "Java,大数据,前端,云计算"
  • Map
 const m = new Map();
        m.set('name','ATGUIGU');
        const result = Object.fromEntries(m);
        console.log(result)
        //{name: "ATGUIGU"}
  • Object.entries和它相反
const arr = Object.entries({
            name: "尚硅谷"
        })
        console.log(arr);
        //[Array(2)]
        //0: (2) ["name", "尚硅谷"]
        //length: 1

trimStart trimEnd

  • 清除左边和右边空白
 <script>    
        // trim
        let str = '   iloveyou   ';

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

Array.prototype.flat

  • flat 平

  • 将多维数组转化为低位数组

  • 参数为深度 是一个数字

    • 三维转1维输入2
    • 默认值是1
const arr = [1,2,3,4,[5,6]];
        console.log(arr.flat()); 
        (6) [1, 2, 3, 4, 5, 6]
const arr = [1,2,3,4,[5,6,[7,8,9]]];
        console.log(arr.flat());  
        (7) [1, 2, 3, 4, 5, 6, Array(3)]
const arr = [1,2,3,4,[5,6,[7,8,9]]];
        console.log(arr.flat(2)); 
        //(9) [1, 2, 3, 4, 5, 6, 7, 8, 9]

flatMap

  • 跟Map很像,只是把维度降低

  • 两个操作结合

		const arr = [1,2,3,4];
        const result = arr.map(item => item * 10);
        console.log(result)
        //(4) [10, 20, 30, 40]
----------------------------------------------------
        const arr = [1,2,3,4];
        const result = arr.map(item => [item * 10]);
        console.log(result)
        //0: [10]
        //1: [20]
        //2: [30]
        //3: [40]
--------------------------------------------------------------
        const arr = [1,2,3,4];
        const result = arr.flatMap(item => [item * 10]);
        console.log(result);
        //(4) [10, 20, 30, 40]

Symbol.prototype.description

  • 获取Symbol的描述字符串
<script>
        //创建 Symbol
        let s = Symbol('尚硅谷');

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

ECMAScript11

类的私有属性

 <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);
        //Private field '#age' must be declared in an enclosing class

        girl.intro();  //晓红 18  45
    </script>

Promise.allSettled

  • 接收promise一个数组,返回的promise结果也是对象,不过返回的结果永远是一个成功的状态.而且成功的值是里边每一个promise状态和结果
<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>

String.prototype.matchAll

  • 用来得到正则批量匹配的结果
<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>

.? 可选链操作符

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

动态 import 导入

<body>
    <button id="btn">点击</button>
    <script src="./js/app.js" type="module"></script>
</body>
export function hello(){
    alert('Hello');
}
// import * as m1 from "./hello.js";
//获取元素
const btn = document.getElementById('btn');

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

BigInt 大整形

  • 不能直接与数值计算
  • 不能使用浮点数计算
 <script>
        //大整形
        let n = 521n;
        console.log(n, typeof(n));
        //521n "bigint"

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

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

        console.log(BigInt(max))
        console.log(BigInt(max) + BigInt(1))
        console.log(BigInt(max) + BigInt(2))
    </script>

绝对全局对象globalThis

  • 始终指向全局对象
 <script>
        console.log(globalThis);   //window
 </script>
console.log(globalThis);  //globakThis
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值