ES学习笔记

ES6

一. ECMAScript相关介绍

ECMA(European computer Manufacturers Association)欧洲计算机制造商协会,是评估、开发和认可电信和计算机标准的组织

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

版本发行时间特性
第 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 年扩展对象、数组方法
ES.next动态指向下一个版本

TC39(Technical Committee 39)推进 ECMAScript 发展的委员会,维护ECMA-262。

二.let和const

1.Let声明变量特性:

1.变量不可重复声明,var可以

2.块级作用域:只在代码块中有效;var没有

ES5中作用域包括:全局,函数,eval(ES5严格模式里才出现)

3.不存在变量提升

4.不影响作用域链

    // 声明变量
        let a,b,c;
        let d="zsy", e=0, h=[];
        let school = "尚硅谷";
        console.log(school);
        // 块级作用域
        {
            let school="朱世英";
            console.log("块级作用域---->"+school);
        }
        // 不存在变量提升
        {
            // console.log("变量提升姓名:"+name);
            // let name = "zsy";
        }
        // 不影响作用域链

        let xuexiao = "尚硅谷";
        {
            let college = "atguigu";
            function School(){
                console.log("作用域链---->"+xuexiao);
                console.log("作用域链---->"+college);
            }
            School();
        }
2.Const声明变量特性

const一般用于声明常量,即值不可修改的量。

常量声明必须注意:

1.一定要赋初始值;

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

3.常量值不可修改

4.块级作用域

5.对于数组和对象的元素修改,不算做对常量的修改,不会报错,因为地址没变。

三.变量的解构赋值

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

   // 1.数组的解构赋值
        const F4 = ['小沈阳','刘能','赵四','宋小宝'];
        let [xiao,liu,zhao,song] = F4;
        console.log(xiao);
        console.log(liu);
        console.log(zhao);
        console.log(song);
        // 2.对象的解构赋值
        const bensan = {
            name:'赵本山',
            age: 43,
            xiaopin: function(){
                console.log("演小品");
            }
        }
        /* 与顺序无关,与属性名有关  
        let {name,age,xiaopin} = bensan;
        console.log(name);
        console.log(age);
        console.log(xiaopin);
        xiaopin(); 
        */
        let {xiaopin} = bensan ;
        console.log(xiaopin);

四.模板字符串

ES5中声明字符串用单引号(‘ ’)或双引号(“ ”)

ES6中引入新的声明字符串方式:反引号(``)

特性:1.内容中可以直接出现换行符

​ 2.可以变量拼接

let loveshot = '魏翔';
let out = `${loveshot}是最棒的!`;
console.log(out); //魏翔是最棒的!

五.对象的简化写法

ES6中允许在大括号里直接写入变量和函数,作为对象的属性和方法。(写法更简洁)

let name = "zsy";
let change = function(){
	console.log('我们可以改变你!');
}
const school = {
	name,
	change,
	improve(){
		console.log('提高技能');
	}
}

六.箭头函数

函数声明及调用:

 /*之前写法
        let fn = function(){

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

1.this是静态的,this始终是指向函数声明时所在作用域下的this的值

  // 验证this
        // 普通函数
        function getName(){
            console.log("普通函数this--->"+this);
            console.log(this.name);
        }
        //箭头函数:写在window全局作用域下
        let getName2 = () => {
            console.log("箭头函数this--->"+this);
            console.log(this.name);
        }
        // 设置window对象的name属性
        window.name ='尚硅谷';
        const school = {
            name:"atguigu"
        }
        // 直接调用
        getName();//普通:尚硅谷 普通函数this--->[object Window]
        getName2();//箭头:尚硅谷 普通函数this--->[object Window]
        // call方法调用
        getName.call(school); //普通:atguigu 普通函数this--->[object Object]
        getName2.call(school); //箭头:尚硅谷  箭头函数this--->[object Window]

call方法:

2.不能作为构造函数实例化对象

        // 验证构造
        // 报错:Uncaught TypeError: Person is not a constructor
        let Person =(name ,age)=>{
            this.name = name;
            this.age = age;
        }
        let me = new Person('zsy',22);
        console.log(me);

3.不能使用arguments变量(用于保存实参)

        //报错: Uncaught ReferenceError: argumrnts is not defined
        let fn =()=>{
            console.log(argumrnts);
        }
        fn(1,2,3)

4.箭头函数简写

​ 1)省略小括号,当形参有且只有一个时

        let add = n =>{
            return n+n;
        }
        console.log(add(9));//18

​ 2)省略花括号,当代码体只有一条语句时,此时return也必须省略,且语句执行结果为函数返回值

     let pow = n => n*n;
        console.log(pow(9)); //81

5.应用场景

箭头函数适用于与this无关的回调函数,eg.定时器,数组的方法回调

箭头函数不适用于与this有关的回调,eg.事件回调,对象的方法

七.ES6函数参数初始值设置

1.形参初始值,具有默认值的参数,一般位置靠后(潜规则)

 function fn(a,b,c=10){
            console.log(a,b,c);
        }
        fn(1,2,3)//1 2 3
        fn(1,2)//1 2 10

2.可与解构赋值结合使用

  function z({name= 'zsy',age,school}){
            console.log(name,age,school);
        }
        z({
            name:'zz',
            age: 22,
            school:'tj'
        })//zz 22 tj
        z({
            age: 22,
            school:'tj'
        })//zsy 22 tj

八.rest参数

ES5获取实参方式:结果为对象

 function fn(){
            console.log(arguments);
        }
        fn('z','s','y');
        //Arguments(3) ['z', 's', 'y', callee: ƒ, Symbol(Symbol.iterator): ƒ]

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

结果是数组,可使用数组的一些方法

 function data(...args){
            console.log(args);
        }
        data('zz','ss','yy')
        //(3) ['zz', 'ss', 'yy']

注意:rest参数必须要放到参数最后

九.扩展运算符[…]

ES6的扩展运算符能将数组转化为逗号分割的参数序列

    const tf = ['zsy','ysz','syz'];
        function mz(){
            console.log(arguments);
        }
        mz(tf)
        //Arguments(1)0: (3) ['zsy', 'ysz', 'syz']
        mz(...tf)
        //Arguments(3) ['zsy', 'ysz', 'syz', callee: ƒ, Symbol(Symbol.iterator): ƒ]
        //0: "zsy"
       //1: "ysz"
       //2: "syz

使用场景:

1.数组的合并

const kzxd=['wtl','xy'];
const fhcq = ['lh','zy'];
const zh = kzxd.concat(fhcq);//ES5
const zh1 = [...kzxd , ...fhcq]//ES6

2.数组的克隆(对于对象是浅拷贝)

cosnt mz = ['Z','S','Y'];
cosnt NM = [...mz];

3.伪数组转成真正数组 (也可转arguments,但有了rest所以一般不用)

cosnt divs = document.querySelectorAll('div');
const divArr = [...divs];

十.Symbol的基本使用

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

特点

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

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

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

创建
  // 创建Symbol
        let s = Symbol();
        console.log(s,typeof s); //Symbol() 'symbol'
        //其唯一性不可见
		//普通创建
        let s2 = Symbol('zsy');
        let s3 = Symbol('zsy');
        console.log(s2 === s3); //false
        // Symbol.for方法创建
        let s4 = Symbol.for('zsy');
        let s5 = Symbol.for('zsy');
        console.log(s4,typeof s4);//Symbol(zsy) 'symbol'
        console.log(s4 === s5); //true

数据类型:undefined string symbol object null number Boolean

使用场景

给对象添加属性和方法,表示独一无二的

game对象里内容过多不好找是否有方法时,用Symbol再创一个

       //向对象中添加方法 up down
        let game = {
            name: '俄罗斯方块',
            up: function () { },
            down: function () { }
        };
        // 声明一个对象
        let method = {
            up:Symbol(),
            down:Symbol()
        }
        //方一.
        game[method.up] = function(){
            console.log("up---111");
        }
        game[method.down] = function(){
            console.log("down---111");
        }
        console.log(game);

        //方二.
        let youxi = {
            name :'lrs',
            [Symbol('say')]:function(){
                console.log("say---111");
            }
        }
        console.log(youxi);
内置值(Symbol的属性)

Symbol内置值可做对象的属性,通过设置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)方法调用时,会返回 该方法的返回值。
bol.split当该对象被 str.split(myObject)方法调用时,会返回该 方法的返回值。
Symbol.iterator对象进行 for…of 循环时,会调用 Symbol.iterator 方法, 返回该对象的默认遍历
Symbol.toPrimitive该对象被转为原始类型的值时,会调用这个方法,返 回该对象对应的原始类型值。
Symbol. toStringTag在该对象上面调用 toString 方法时,返回该方法的返 回值
Symbol. unscopables该对象指定了使用 with 关键字时,哪些属性会被 with 环境排除。
//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)是一种接口(是对象里的一个属性Symbol.Iterator),为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署 Iterator 接口,就可以完成遍历操作。

(1)ES6创造了一种新的遍历命令for…of循环,Iterator主要供for…of使用

for…of保存键值;for…in保存键名

(2)原生具备迭代器的数据(可用 for of 遍历)

​ a) Array

​ b) Arguments

​ c) Set

​ d) Map

​ e) String

​ f) TypedArray

​ g) NodeList

(3) 工作原理

​ a) 创建一个指针对象,指向当前数据结构的起始位置

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

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

​ d) 每调用 next 方法返回一个包含 value 和 done 属性的对象 注: 需要自定义遍历数据的时候,要想到迭代器。

Symbol.Iterator是一个函数,内有一个next方法。

(4)应用:自定义遍历数据

  const banji = {
            stus:[
                "小明",
                "小红",
                "小刚",
                "小天"
            ],
            [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);
        }

十二.生成器

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

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

文件操作,网络操作(Ajax request),数据库操作

注意
    • 的位置没有限制
  1. 生成器函数返回的结果是迭代器对象,调用迭代器对象的 next 方法可以得到 yield 语句后的值

  2. yield 相当于函数的暂停标记,也可以认为是函数的分隔符,每调用一次 next 方法,执行一段代码

  3. next 方法可以传递实参,作为 yield 语句的返回值

生成器声明及调用
       function *gen() {
            console.log("hello generator");
        }
        let iterator = gen();
        console.log(iterator); //gen {<suspended>} gen函数迭代器
        iterator.next(); //hello generator

生成器与yield结合使用

      function *gene() {
            console.log(111);
            yield '一只没有耳朵';
            console.log(222);
            yield '一只没有尾巴';
            console.log(333);
            yield '真奇怪',
            console.log(444);
        }
        let it = gene();
        it.next(); //111
        it.next(); //222
        it.next(); //333
        it.next(); //444
		//遍历
		for (let v of gene()) {
            console.log(v);
        }
		/*
		111
		一只没有耳朵
		222
		一只没有尾巴
		333
		真奇怪
		444
		*/
生成器函数参数
  //生成器函数参数
        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());
        // next可以传入参数
        console.log(iterator.next('BBB'));
        console.log(iterator.next('CCC'));
        console.log(iterator.next('DDD'));
/*
AAA
{value: 111, done: false}
BBB
{value: 222, done: false}
CCC
{value: 333, done: false}
DDD
{value: undefined, done: true}
*/
实例

需求: 1s后111 2s后222 3s后333

//回调地狱
        setTimeout(()=>{
            console.log(111);
            setTimeout(()=>{
                console.log(222);
                setTimeout(()=>{
                    console.log(333);
                },1000)
            },1000)
        },1000)
        
//生成器函数
        function one() {
            setTimeout(()=>{
                console.log(111);
                iterator.next();
            },1000);
        }
        function two() {
            setTimeout(()=>{
                console.log(222);
                iterator.next();
            },1000);
        }
        function three() {
            setTimeout(()=>{
                console.log(333);
                iterator.next();
            },1000);
        }
        function *gen() {
            yield one();
            yield two();
            yield three()
        }

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

十三.Promise

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

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

  2. Promise.prototype.then 方法

  3. Promise.prototype.catch 方法

基本使用
  const p = new Promise(function (resolve,reject) {
            setTimeout(function () {
                //获取数据成功
                let data = '数据库中的用户数据';
                //resolve 改变promise对象状态为成功
                resolve(data);
                /* resolve和reject二选一*/
                // 获取数据失败
                let err = '数据读取失败';
                //reject 改变promise对象状态为失败
                reject(err);
            },1000)
        });

        p.then(function (value) {
            console.log(value);
        },function (reason) {
            console.log(reason);
        })
封装读取文件

先按node.js环境

(1)node自带fs方法读取

    //需求:读取resources中《为学》的内容
    //1.引入fs模块 
    const fs = require('fs');
    //2.调用方法读取文件. err出错为错误对象,失败为null
    fs.readFile('./resources/为学.md',(err,data)=>{
        // 如果失败,抛出错误
        if(err) throw err;
        // 如果成功,输出内容
        console.log(data.toString());
    })

//node 08.promise.js运行

(2)用Promise封装

    //1.引入fs模块 
    const fs = require('fs');
    //使用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
       //创建对象
        const xhr = new XMLHttpRequest();
        // 初始化
        xhr.open('GET','https://api.apiopen.top/getJoke');
        //发送
        xhr.send();
        //绑定事件,处理响应结果
        xhr.onreadystatechange =function(){
            if(xhr.readyState === 4){
                if(xhr.status >=200 && xhr.status <300){
                    console.log(xhr.response);
                }else{
                    console.log(xhr.status);
                }
            }
        }
       //Promise封装
       const p = new Promise((resolve, reject) => {
            const xhr = new XMLHttpRequest();
            // 初始化
            xhr.open('GET', 'https://api.apiopen.top/getJoke');
            //发送
            xhr.send();
            //绑定事件,处理响应结果
            xhr.onreadystatechange = function () {
                if (xhr.readyState === 4) {
                    if (xhr.status >= 200 && xhr.status < 300) {
                        resolve(xhr.response);
                    } else {
                        reject(xhr.status);
                    }
                }
            }
        })

        // 指定回调
        p.then(function (value) {
            console.log(value.toString());
        }, function (reason) {
            console.log(reason);
        })
Promise.prototype.then 方法

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

如果回调函数中返回结果是非promise类型数据,状态为成功,返回值为对象成功值

  const p = new Promise((resolve,reject)=>{
            setTimeout(()=>{
                resolve("用户数据")
            },1000)
        })
        // 调用then方法
        const result = p.then(value=>{
            console.log(value);
            return '111'
        },reason=>{
            console.log(reason);
        })
        console.log(result);
	 /*
        Promise {<pending>}
        [[Prototype]]: Promise
        [[PromiseState]]: "fulfilled"
        [[PromiseResult]]: "111"
        */

如果回调结果是一个Promise对象

        const p = new Promise((resolve,reject)=>{
            setTimeout(()=>{
                resolve("用户数据")
            },1000)
        })
        // 调用then方法
        const result = p.then(value=>{
            console.log(value);
           /* return new Promise((resolve,reject)=>{
               // resolve('ok');
                reject('error');
            })*/
             throw '出错了' 
        },reason=>{
            console.log(reason);
        })
        console.log(result);
       /*return resolve
       Promise {<pending>}
        [[Prototype]]: Promise
        [[PromiseState]]: "fulfilled"
        [[PromiseResult]]: "ok"
       */
      /*returen reject
      Promise {<pending>}
        [[Prototype]]: Promise
        [[PromiseState]]: "rejected"
        [[PromiseResult]]: "error"
      */
      /*throw "出错了"
      Promise {<pending>}
        [[Prototype]]: Promise
        [[PromiseState]]: "rejected"
        [[PromiseResult]]: "出错了"
      */

then方法可以链式调用

Promise.prototype.catch 方法
        const p = new Promise((resolve, reject)=>{
            setTimeout(()=>{
                //设置 p 对象的状态为失败, 并设置失败的值
                reject("出错啦!");
            }, 1000)
        });
        p.catch(function(reason){
            console.log(reason);
        });
实例

需求:读取多个文件

const fs = require('fs');
const { resolve } = require('path/posix');
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 instanceof Array); //true
    console.log(value.join('\r\n'));
})

十四.SET

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

集合的属性和方法:

​ 1) size 返回集合的元素个数

​ 2) add 增加一个新元素,返回当前集合

​ 3) delete 删除元素,返回 boolean 值

​ 4) has 检测集合中是否包含某个元素,返回 boolean 值

​ 5) clear 清空集合,返回 undefined

        let s= new Set();
        let s2 = new Set(['大','小','坏','好','大']);
        // 个数
        console.log(s2.size); //4
        //添加
        s2.add('喜'); //大,小,坏,好,喜
        //删除
        s2.delete('大') ;//小,坏,好,喜
        //检测
        console.log(s2.has('好'));//true
        //清除
        s2.clear();
        for (let v of s2) {
            console.log(v);
        }
实践
 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;
             }
         });//4,5
		//简化方法
         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. 差集 在arr不在arr2
        let diff = [...new Set(arr)].filter(item => !(new Set(arr2).has(item)));
        console.log(diff);

十五.Map

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

Map 的属性和方法:

​ 1) size 返回 Map 的元素个数

​ 2) set 增加一个新元素,返回当前 Map

​ 3) get 返回键名对象的键值

​ 4) has 检测 Map 中是否包含某个元素,返回 boolean 值

​ 5) clear 清空集合,返回 undefined

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

        //添加元素
        m.set('name','尚硅谷');
        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();

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

        //console.log(m);

十六.Class类

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

知识点

​ 1) class 声明类

​ 2) constructor 定义构造函数初始化

​ 3) extends 继承父类

​ 4) super 调用父级构造方法

​ 5) static 定义静态方法和属性

​ 6) 父类方法可以重写

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

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

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

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

        console.log(onePlus);
class静态成员

ES5中函数对象上的属性方法,实例对象看不到,实例对象只能看到函数对象的原型上的方法属性。

这些函数对象上看不到的属性方法,称为静态成员

ES6中属于类,不属于实例对象的称为静态成员,声明关键字为static

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

        let nokia = new Phone();
        console.log(nokia.name);
        console.log(Phone.name);
ES6-ES5构造函数的继承

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); //Phone的this改为smartPhone的this
            this.color = color;
            this.size = size;
        }
        // 设置子级构造函数的原型
        SmartPhone.prototype = new Phone; 
        //更改子级的显示原型为父级实例对象,及其__proto__与Phone的prototype指向相同,可调用call('打电话')
        SmartPhone.prototype.constructor = SmartPhone;
		//constructor矫正
        // 声明子类的方法
        SmartPhone.prototype.photo = function(){
            console.log("拍照");
        }

        const Apple = new SmartPhone('苹果',2444,'red','5.5inch')
        console.log(Apple);

//子类方法在__proto__上,父类方法在__proto__的__proto__上

ES6类继承

        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);
                this.color = color;
                this.size =size
            }
            photo(){
                console.log('拍照');
            }
        }
        
        const Apple = new SmartPhone('苹果',2444,'red','5.5inch')
        console.log(Apple);

在ES6中子类可以重写父类中同名方法,但子类不可直接调用父类的同名方法,即使用super(),也报错

class中Getter和Setter方法
 class Phone{
     		//封装动态属性
            get price(){
                console.log("价格属性被读取了");
                return 'iloveyou';
            }

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

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

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

十七.ES6数值扩展

(1) Number.EPSILON 是 JavaScript 表示的最小精度

​ EPSILON 属性的值接近于 2.2204460492503130808472633361816E-16

​ 若两个数之间误差小于Number.EPSILON,则认为其相等

function equal(a, b){
    		 //Math.abs()取绝对值
            if(Math.abs(a-b) < Number.EPSILON){
                return true;
            }else{
                return false;
            }
        }
        console.log(0.1 + 0.2 === 0.3);//false
        console.log(equal(0.1 + 0.2, 0.3))//true

(2)引入二进制和八进制表示

        let b = 0b1010; //10 二进制
        let o = 0o777;  //511	八进制
        let d = 100;    //100 十进制
        let x = 0xff;   //255 十六进制

(3)Number.isFinite 检测一个数值是否为有限数

console.log(Number.isFinite(100)); //true
console.log(Number.isFinite(100/0)); //false
console.log(Number.isFinite(Infinity)); //false

(4)Number.isNaN 检测一个数值是否为 NaN

        console.log(Number.isNaN(123)); //false

(5)Number.parseInt Number.parseFloat字符串转整数

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

(6)Number.isInteger 判断一个数是否为整数

        console.log(Number.isInteger(5)); //true
        console.log(Number.isInteger(2.5)); //false

(7)Math.trunc 将数字的小数部分抹掉

        console.log(Math.trunc(3.5)); //3

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

        console.log(Math.sign(100)); //1
        console.log(Math.sign(0));	//0
        console.log(Math.sign(-20000));	//-1

十八.对象扩展

  1. Object.is 判断两个值是否完全相等 ,与『===』行为基本一致
        console.log(Object.is(120, 120));// true
        console.log(Object.is(NaN, NaN));// true
        console.log(NaN === NaN);// false
		console.log(Object.is(+0, -0)); //false
        console.log((+0 === -0));		//true
  1. 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));
    //config1模板,config2覆盖config1
    

    ​ 3. Object.setPrototypeOf 设置原型对象 Object.getPrototypeof获取原型对象(方法不推荐)

        const school = {
            name: '尚硅谷'
        }
        const cities = {
            xiaoqu: ['北京','上海','深圳']
        }
        Object.setPrototypeOf(school, cities);
        console.log(Object.getPrototypeOf(school)); 
        console.log(school);

十九.模块化

概念

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

好处:

​ 1) 防止命名冲突

​ 2) 代码复用

​ 3) 高维护性

模块化产品

(ES6 之前的模块化规范)

  1. CommonJS => NodeJS、Browserify

  2. AMD => requireJS

  3. CMD => seaJS

语法

模块功能主要由两个命令构成:export 和 import。

  1. export 命令用于规定模块的对外接口 (暴露)

    分别暴露

    export let school = '123';
    export function teach(){
    	console.log("222");
    }
    

    统一暴露

    let school = '123';
    function teach(){
    	console.log("222");
    }
    export {school,teach}
    

    默认暴露

    export default{
        school:'111',
        teach: function(){
            console.log("222");
        }
    }
    
  2. import 命令用于输入其他模块提供的功能(导入)

    通用方式:

    import * as mz from './src/js/m.js'
    

    解构赋值方式

    import {school,teach} from "./src/js/m.js"
    import {school as xuexiai ,teach} from "./src/js/m.js"
    //引入不可重名,重名采用别名方式解决
    import {default as m} from "./src/js/m.js"
    //不可直接用default,必须设别名
    

    简便形式----只针对默认暴露

    import m from './src/js/m.js' //文件名字
    
    模块化方式二

    HTML文件引入script

        <script src="入口文件名.js" type="module"></script>
    

    入口文件名.js 里面只写引入部分的import

    babel转换ES6模块化代码

    项目一般不用方式二,因为:兼容性,且ES6模块化还不可直接对NPM安装的一些模块进行导入

    转化步骤:

    1.安装工具 babel-cli(命令行工具)babel-preset-env(预设包) browerify(打包工具)

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

    2.语法转换

    //全局安装
    babel src/js(原文件目录)-d(转到哪儿) dist/js(转化后目录) --presets=babel-preset-env
    //局部安装
    npx babel src/js(原文件目录)-d dist/js --presets=babel-preset-env
    

    3.打包

    npx browserify dist/js/app.js(入口文件) -o dist/bundle.js(输出文件)
    

    注意:原文件改变要重新转化打包

ES6使用NPM包

1.安装npm包和babel

  1. $—变量名 ‘jQuery’-----NPM包名
import $ from 'jQuery' //const $ = require("jquery")

3.重打包

ES7

Array.prototype.includes Includes 方法

用来检测数组中是否包含某个元素,返回布尔类型值。存在true,不存在false

  const mingzu = ['西游记','红楼梦','三国','水浒传'];
  console.log(mingzu.includes('西游记')); //true

之前用indexof,返回结果 存在是下标,不存在是-1

指数操作符

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

(Math.pow(x,y)-----求x的y次幂)

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

ES8

异步编程解决方法:生成器函数,promise,async ,await

一.async 和 await

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

async 函数
  1. async 函数的返回值为 promise 对象

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

    //返回结果不是Promise类型对象,则结果为成功的Promise对象
    async function fn(){
            return 'zsy';
    	}
    const result = fn();
    console.log(result);
    /*
    Promise {<fulfilled>: 'zsy'}
    [[Prototype]]: Promise
    [[PromiseState]]: "fulfilled"
    [[PromiseResult]]: "zsy"
    */
    //抛出错误,返回失败的promise
    async function fn(){
            throw new Error('出错了!!')
    	}
    const result = fn();
    console.log(result);
    
    //返回Promise,结果同promise结果
    
await函数
  1. await 必须写在 async 函数中

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

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

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

  const p = new Promise((resolve, reject) => {
            // resolve('成功值'); //成功值
            reject("失败") //失败
        })
        async function main() {
            try {
                let result = await p;
                console.log(result);
            } catch (error) {
                console.log(error);
            }
        }
        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请求
     // 发送 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();

二.对象方法拓展

Object.values 和 Object.entries
  1. Object.values()方法返回一个给定对象的所有可枚举属性值的数组

  2. Object.entries()方法返回一个给定对象自身可遍历属性 [key,value] 的数组,方便创建Map

             //声明对象
             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'));
    
Object.getOwnPropertyDescriptors

该方法返回指定对象所有自身属性的描述对象(结果类似Object.create()创建的对象)

        //对象属性的描述对象
        console.log(Object.getOwnPropertyDescriptors(school));
		//第二个参数是且只是对象
        const obj = Object.create(null, {
            name: {
                //设置值
                value: '尚硅谷',
                //属性特性
                writable: true,
                configurable: true,
                enumerable: true
            } 

ES9

一.Rest参数与扩展运算符

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

二.正则表达

命名捕获组

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

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);
反向断言

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

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

正则表达式中点.匹配除回车外的任何单字符,标记『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>.*?<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);

ES10

1.Object.fromEntries (ES8 Object.entries()的逆运算)

接收参数为二位数组或一个Map

 //二维数组
        const result = Object.fromEntries([
            ['name','尚硅谷'],
            ['xueke','JAVA,MYSQL']
        ])
        console.log(result);

2.trimStart 和 trimEnd

指定清除字符串左右侧空白,trimStart清除左侧,trimEnd清除右侧

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

3.Array.prototype.flat 与 flatMap

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

flatMap将Map结果做维度降低

//flat 
const arr = [1,2,3,4,[5,6]];
const arr = [1,2,3,4,[5,6,[7,8,9]]];
// 参数为深度 是一个数字
console.log(arr.flat(2));

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

4.Symbol.prototype.description

Symbol的扩展,获取字符串的描述

 let s = Symbol('尚硅谷');
 console.log(s.description);//尚硅谷

ES11

  1. 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
    
            //调用方法
            const result = str.matchAll(reg);
    
            // for(let v of result){
            //     console.log(v);
            // }
    
            const arr = [...result];
    
            console.log(arr);
    
  2. 类的私有属性

     class Person{
                //公有属性
                name;
                //私有属性
                #age;
                #weight;
                //构造方法
                constructor(name, age, weight){
                    this.name = name;
                    this.#age = age;
                    this.#weight = weight;
                }
    
                intro(){
                    console.log(this.name);
                    console.log(this.#age);
                    console.log(this.#weight);
                }
            }
    
            //实例化
            const girl = new Person('晓红', 18, '45kg');
    
            // console.log(girl.name);
            // console.log(girl.#age);私有属性不可获取
            // console.log(girl.#weight);
    
            girl.intro();
    
  3. Promise.allSettled

    接收一个promise数组,返回结果是promise对象,但结果永远是成功状态,值为数组中每个promise的结果

    //声明两个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]); 
    //结果是两个元素相与的结果,失败返回值为失败的值
    
  4. 可选链操作符

    【?.】当应对对象类型的参数时,对象层级比较深的情况

     function main(config){
                // const dbHost = config && config.db && config.db.host;
         		//&&在两边运算结果都为true时返回右边值
                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'
                }
            })
    
  5. .动态 import 导入

    实现按需加载,返回值为promise,成功值为暴露对象

    import('./hello.js').then(module =>{
        console.log('module');
    })
    
  6. .globalThis 对象

    始终指向全局对象

    console.log(globalThis);
    
  7. BigInt类型(大整型)

    用于大数字运算

     //表示方法
             let n = 521n;
             console.log(n, typeof(n));
    
            //函数,数字转换为bigint型,浮点型数字不可转
             let n = 123;
             console.log(BigInt(n));
             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))
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值