javaScript ES6-ES11新特性总结

ES6-ES11新特性知识点

一、ES6

1、查看ES6兼容性

http://kangax.github.io/compat-table/es6/ 可查看兼容性

2、let定义变量

快速入门:

//特点:
//1.let变量不能重复声明,只在当前块生效
//2.不存在变量提升
//3.不影响作用域链效果
//4.存在 暂时性死区:代码块内,使用let命令声明变量之前,该变量都是不可用的
let star = '小猪';

深入理解:

3、const定义常量

快速入门:

//特点:
//1.const声明常量时必须赋初值,值一旦确认便不可修改,一般常量名大写(代码规范)
//2.const常量同块内不能重复声明,只在当前块生效
//3.不影响作用域链效果
//4.不存在变量提升
//5.存在暂时性死区:代码块内,使用const命令声明常量之前,该常量都是不可用的
const star = '小猪';

深入理解:

4、作用域

快速入门:

ES6之后作用域为:
	全局作用域、函数作用域、{}块级作用域(新增)、
	eval(ES严格模式下存在)

深入理解:

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 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 内部函数属性同名
        let {xiaopin} = zhao;
        xiaopin();//我可以演小品

深入理解:

6、模板字符串

快速入门:

// ES6 引入新的声明字符串的方式 『``』 反引号
//语法
let str1=`我也是一字符串哦`
//2. 内容中可以直接出现换行符
let str2 = `<ul>
           <li>沈腾</li>
           <li>玛丽</li>
           <li>魏翔</li>
           <li>艾伦</li>
           </ul>`;
//3. 变量拼接 ${}
let lovest = '魏翔';
let out = `${lovest}是我心目中最搞笑的演员!!`;
console.log(out);

深入理解:

7、简化对象写法

快速入门:

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

       //ES6允许在大括号里面,直接写入变量和函数名,作为对象的属性和方法
       // ES6还允许在对象中声明函数时,去掉:和function
        let SCHOOL = {
            name,//等价于name:name
            change,//等价于change(){}
            //简化函数声明等价于improve:function(){}
            improve(){
                console.log("我们可以提高你的技能");
            }
        }

        console.log(school);

</script>

8、箭头函数

快速入门:

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

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


//1.箭头函数 this 是静态的. this 始终指向函数声明时所在作用域下的this 的值,不可改变
function getName(){
      console.log(this.name);
}
let getName2 = () => {
       console.log(this.name);
}
//设置 window 对象的 name 属性
window.name = '尚硅谷';
const school = {
    name: "ATGUIGU"
}
//直接调用
// getName(); //尚硅谷
// getName2(); //尚硅谷

//call 方法调用
// getName.call(school);//ATGUIGU 普通函数this指向调用它的对象
// getName2.call(school);//尚硅谷  箭头函数this依旧指向window


//2. 不能作为构造函数实例化对象 报错Unacught TypeError:XXX is not a constructor 
// let Person = (name, age) => {
//     this.name = name;
//     this.age = age;
// }
// let me = new Person('xiao',30);
// console.log(me);

//3.不能使用 arguments 变量  报错Uncaught ReferenceError:arguments is not defined
 // let fn = () => {
        //     console.log(arguments);
        // }
        // 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(8));//64

9、参数默认值


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


        //2.可以 与解构赋值结合
        function connect({
            host = "127.0.0.1", //默认值 会被传入覆盖
            username,
            password,
            port
        }) {
            console.log(host)
            console.log(username)
            console.log(password)
            console.log(port)
        }
        
        let option = { //this指向 option
            host: this.host,
            username: this.username,
            password: this.password,
            port: this.port
        }
        option.host = "localhost"
        option.username = "user"
        //解构赋值  类似 {host,username,password,port}=option 
        connect(option)

10、rest参数


        // 新特性:ES6 引入 rest 参数,用于获取函数的实参,用来代替 arguments

        // ES5 获取实参的方式

        // function date(){
        //     console.log(arguments);
        // }
        // date('白芷','阿娇','思慧');

        // rest 参数 获取实参的方式

        // function date(...args){  //res参数  ...args 可变参数列表 是一个数组
        //     console.log(args);// 因为是数组 所以可以传入 filter some every map 
        // }
        // date('阿娇','柏芝','思慧');

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

11、拓展运算符

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

        //声明一个数组 ...
        const tfboys = ['易烊千玺', '王源', '王俊凯'];

        // 声明一个函数
        function chunwan() {
            console.log(arguments); // '易烊千玺','王源','王俊凯'

        }

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

与rest参数不同的是 拓展运算符书写在 函数调用的实参位置

应用场景:

<body>
    <div></div>
    <div></div>
    <div></div>
    <script>
        //1. 数组的合并 情圣  误杀  唐探
        // const kuaizi = ['王太利','肖央'];
        // const fenghuang = ['曾毅','玲花'];
        // //ES5做法 const zuixuanxiaopingguo = kuaizi.concat(fenghuang);
        // ES6做法: 拓展运算符
        // const zuixuanxiaopingguo = [...kuaizi, ...fenghuang];
        // console.log(zuixuanxiaopingguo);

        //2. 数组的克隆  
        // const sanzhihua = ['E','G','M'];
        // const sanyecao = [...sanzhihua];//  ['E','G','M'] 数组内部若存在引用类型则为浅拷贝
        // console.log(sanyecao);

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

12、Symbol

**含义:**ES6引入的一种新的数据类型 Symbol,表示独一无二的值,

主要作用是给对象添加属性和方法

是js第七种数据类型

特点

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

2、Symbol值不能与其他数据类型进行运算

3、 Symbol定义的对象属性不能使用 for…in循环遍历,

​ 但可以使用Reflect.ownKeys来获取对象的所有键名

一、创建方式

 //创建Symbol
        //Symbol是一个函数对象
        let s = Symbol();
        //console.log(s, typeof s);
		//Symbol('xuexi') 这种方式创建的Symbol值是变化的 
        let s2 = Symbol('xuexi'); // xuexi是类似注释的功能
        let s3 = Symbol('xuexi');
        console.log(s2 === s3); //false 

        //Symbol.for 创建   for() 根据参数字符串创建Symbol,得到唯一的Symbol值
		// Symbol.for('xuexi') 这种方式创建的Symbol值是不变的
        let s4 = Symbol.for('xuexi');
        let s5 = Symbol.for('xuexi');
        console.log(s4 === s5); //true

        //注意点
        //不能与其他数据进行运算
        //ncaught TypeError: Cannot convert a Symbol value to a number at
        //let result = s + 100;
        //    let result = s > 100;
        //    let result = s + s;

        // USONB  you are so niubility  Js七种数据类型
        // u  undefined
        // s  string  symbol
        // o  object
        // n  null number
        // b  boolean

二、应用场景

   //向对象中添加方法 up down
        //ES5方式 
        //若在已存在的对象上进行添加属性时,
        //直接声明方式可能存在与原对象属性命名冲突问题
        let game = {
            name: '俄罗斯方块',
            up: function () {},
            down: function () {}
        };


        //ES6 利用Symbol解决
        //添加方式一:
        // let methods = {
        //     up: Symbol(),
        //     down: Symbol()
        // };

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

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

        // console.log(game);

        //添加方式二
        let youxi = {
            name: "狼人杀",
            [Symbol('say')]: function () {
                console.log("我可以发言")
            },
            [Symbol('zibao')]: function () {
                console.log('我可以自爆');
            }
        }
        console.log(youxi)
        //youxi[Symbol('say')]();报错 无法调用 因为 Symbol('say') 方式创建Symbol的值是动态变化的
        //console.log(Symbol('say')===Symbol('say')); false
        youxi[Reflect.ownKeys(youxi)[1]](); //调用方法

三、内置属性

//Symbol内置属性 控制对象在特定情景下的表现 定义后在特定场景自动触发 拓展了对象的功能

        //1. 例子 Symbol.hasInstance
        //其他对象 与当前对象进行instanceof时 [Symbol.hasInstance] 会被触发调用 控制类型检测
        // class Person{
        //     static [Symbol.hasInstance](param){ //param实参为 instanceof表达式左侧内容
        //         console.log(param);
        //         console.log("我被用来检测类型了");
        //         return false;//instanceof结果为false
        //     }
        // }

        // let o = {};

        // console.log(o instanceof Person);

        //2.例子 [Symbol.isConcatSpreadable]
        // 设置数组是否在合并时展开(数组传化为逗号隔开的数字序列)

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

        // arr2[Symbol.isConcatSpreadable] = false;//不可展开
        // console.log(arr.concat(arr2));//1,2,3,arr2数组

13、迭代器

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

Iterator 在js中指对象的一个属性,也就是Symbol(Symbol.Iterator)

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

原生具备Iterator接口的数据

a) Array

b) Arguments

c) Set

d) Map

e) String

f) TypedArray

g) NodeList

原理

a) Symbol.Iterator返回创建一个指针对象,指向当前数据结构的起始位置

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

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

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

 //声明一个数组
        const xiyou = ['唐僧', '孙悟空', '猪八戒', '沙僧'];
        console.log(xiyou);
        //使用 for...of 遍历数组
        // for(let v of xiyou){
        //     console.log(v);
        // }


        //原理 
        //iterator对象的next方法执行返回 遍历数组 内容
        let iterator = xiyou[Symbol.iterator]();

        //调用iterator对象的next方法
        console.log(iterator.next());
        console.log(iterator.next());
        console.log(iterator.next());
        console.log(iterator.next());
        console.log(iterator.next());

自定义迭代器遍历对象

      //声明一个对象  自定义对象无法使用 for of 遍历
        const banji = {
            name: "六年级一班",
            stus: [
                'xiaoming',
                'xiaoning',
                'xiaotian',
                'knight'
            ],
            /*
            对象进行 for...of 循环时,会调用 Symbol.iterator 方法,
            返回该对象的默认遍历器
            */
            [Symbol.iterator]() {

                //this 当前对象=banji
                let keys = Object.keys(this)
                let len = keys.length
                let values = Object.values(this)
                //索引变量
                let index = 0;
                let _this = this;
                return { //a.返回一个对象 为指针对象
                    next: function () { //b.c.指针对象里设置next方法
                        if (index < len) {
                            //console.log(_this);
                            const result = {
                                value: {
                                    k: keys[index],
                                    v: values[index]
                                },
                                done: false //表遍历未结束
                            };
                            //下标自增
                            index++;
                            //返回结果
                            return result;
                        } else {
                            //d.返回一个包含value合done属性的对象
                            return {
                                value: undefined,
                                done: true //遍历结束
                            };
                        }
                    }
                };
            }
        }

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

14、生成器函数

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

特点:

​ 1、生成器函数执行时是可暂停的,之后又能从暂停处继续执行。(暂停标识:yield

​ 2、其中yield语句类似于return:可以返回一个内部状态值,yield 后跟要返回的内容

​ 但不同的是,return结束函数执行,让生成器对象的done状态变为true

​ yield* 表示将任务交给别的生成器执行

​ 3、调用生成器函数返回一个迭代器

​ 5、生成器执行方法:next()的参数表示上一条yield语句的返回值,所有第一次使用next方法时,传递的参数是无效的。

入门语法示例:

//生成器其实就是一个特殊的函数,主要进行异步编程
        //异步编程  纯回调函数  node fs  ajax mongodb
        //yield 算是函数代码的分隔符,将函数代码分块,next方法分块执行

        //声明方式 *
        function * gen(){
             console.log(111);
            yield '一只没有耳朵';//第一次next()返回 {value: '一只没有耳朵', done: false}
             console.log(222);
            yield '一只没有尾部';//第二次next()返回 {value: '一只没有尾部', done: false}
             console.log(333);
            yield '真奇怪';
             console.log(444);
        }

        let iterator = gen();
        //执行方式:生成器返回迭代器next()调用执行  done:false执行未结束
        console.log(iterator.next());//执行显示 111 返回对象{value: '一只没有耳朵', done: false}
        console.log(iterator.next());//执行显示 222 返回对象{value: '一只没有尾部', done: false}
        console.log(iterator.next());
        console.log(iterator.next());

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

一、生成器函数的参数传递

      //next传入的参数将作为上一个yeild语句的返回结果 
	function * gen(arg){
            console.log(arg);
            let one = yield 111;//111为返回结果
            console.log(one);
            let two = yield 222;
            console.log(two);
            let three = yield 333;
            console.log(three);
        }

        //执行获取迭代器对象
        let iterator = gen('AAA');
		//第一次调用next()
        console.log(iterator.next());

        //第二次调用next()  传入的参数将会是上一个next的返回值
        console.log(iterator.next('BBB'));

        //第三次调用next()
        console.log(iterator.next('CCC'));

        //console.log(iterator.next('DDD'));

      

三、实际应用

案例1:

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

   // 异步编程 应用 :文件操作 网络操作(ajax, request) 数据库操作
        // 任务: 1s 后控制台输出 111  2s后输出 222  3s后输出 333

        // ES5 写法
        // :产生的回调地狱 代码可读性极差
        // setTimeout(() => {
        //     console.log(111);
        //     setTimeout(() => {
        //         console.log(222);
        //         setTimeout(() => {
        //             console.log(333);
        //         }, 3000);
        //     }, 2000);
        // }, 1000);

        //ES6 实现

        //声明第一个异步任务
        function one(){
            setTimeout(()=>{
                console.log(111);
                iterator.next();//调用two()方法
            },1000)
        }

        //声明第二个异步任务
        function two(){
            setTimeout(()=>{

                console.log(222);
                iterator.next();//调用three()方法
            },2000)
        }

        //声明第三个异步任务
        function three(){
            setTimeout(()=>{
                console.log(333);
                iterator.next(); //继续向下调用
            },3000)
        }

        function * gen(){
            //统一管理调用
            yield one();
            yield two();
            yield three();
        }
        //调用生成器函数
        let iterator = gen();
        iterator.next();

案例2:

模拟获取 1、用户数据 2、订单数据 3、商品数据

   //模拟获取 1、用户数据  2、订单数据  3、商品数据

        //定时器模拟  请求过程

        //1、获取用户数据
        function getUsers(UserID){
            setTimeout(()=>{
                console.log("getUsers()获取到的用户数据")
                console.log(UserID)
                let data = '用户数据'+UserID;
                iterator.next(data);//传递给下一个next()的参数将作为本次函数调用的返回值
            }, 1000);
        }

        //2、获取订单数据
        function getOrders(userData){
            setTimeout(()=>{
                console.log("getOrder获取到的用户数据")
                console.log(userData)
                let data = '订单数据'+123456;
                iterator.next(data);
            }, 1000)
        }

        //3、获取商品数据
        function getGoods(orderData){
            setTimeout(()=>{
                console.log("getGoodsr获取到的订单数据")
                console.log(orderData)
                let data = '商品数据';
                iterator.next(data);
            }, 1000)
        }

        function * gen(UserId){
            let users = yield getUsers(UserId);
            let orders = yield getOrders(users);
            let goods = yield getGoods(orders);

        }

        //调用生成器函数
        let iterator = gen("992285544");
         iterator.next();//执行getUser() 

[译] 什么是 JavaScript 生成器?如何使用生成器? - 知乎 (zhihu.com)

15、class

含义:ES6 提供了更接近传统语言的写法,引入了 Class(类)这个概念,作为对

象的模板。

​ 通过 class 关键字,可以定义类。基本上,ES6 的 class 可以看作只是

一个语法糖,它的绝大部分功能,ES5 都可以做到,新的 class 写法只是让对象

原型的写法更加清晰、更像面向对象编程的语法而已。

class定义静态成员属性

//static 修饰成员属性 由类名调用
class Phone{
            //静态属性
            static name = '手机';
            static change(){
                console.log("我可以改变世界");
            }
        }

        let nokia = new Phone();
        console.log(nokia.name);//undeifind
        console.log(Phone.name);//手机 

实现继承

1、es5 方式


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

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

        //智能手机  子类
        function SmartPhone(brand, price, color, size){
            //this.Phone(brand,price)等价于
            //SmartPhone.Phone(brand,price)子类调父类获得父类所有属性和函数
            Phone.call(this, brand, price);
            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);

2、ES6方式

方法重写

很像java的

//父类
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();

get和set方法

 // get 和 set
        class Phone{
            //默认无参构造
            get price(){
                console.log("价格属性被读取了");
                return 'iloveyou';
            }

            set price(newVal){//必须有参数
                console.log('价格属性被修改了');
            }
        }

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

        console.log(s.price);// iloveyou  执行class类中的price()方法
        s.price = 'free';

(49条消息) JavaScript系列—class(静态方法和属性、实例属性、私有方法和属性)_jiaojsun的博客-CSDN博客

16、ES6数值拓展

 //0. Number.EPSILON 是 JavaScript 表示的最小精度,主要解决精度问题

        //EPSILON 属性的值接近于 2.2204460492503130808472633361816E-16
        // function equal(a, b){
        //     //(两数差值 小于最小精度数) 表示 两数字想等解决精度问题
        //     if(Math.abs(a-b) < Number.EPSILON){
        //         return true;
        //     }else{
        //         return false;
        //     }
        // }
        // console.log(0.1 + 0.2 === 0.3);//fasle 不符合常理
        // console.log(equal(0.1 + 0.2, 0.3))

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

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

        //3. Number.isNaN 检测一个数值是否为 NaN(与数字相关) 
        // console.log(Number.isNaN(123)); 

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

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

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

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

17、对象方法拓展

//1. Object.is 判断两个值是否完全相等 
        // console.log(Object.is(120, 120));// === true
        // console.log(Object.is(NaN, NaN));// === true
        //直接=== 永远false
        // console.log(NaN === NaN);// === false

        //2. Object.assign(obj1,obj2) 对象的合并
        // 属性内容冲突时 obj2对象覆盖前面obj1对象
        // 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',
        //     tes2: 'test2'
        // }
        // console.log(Object.assign(config1, config2));

        //3. Object.setPrototypeOf(目标对象,原型对象) 设置原型对象  Object.getPrototypeof
        //不推荐
        const school = {
            name: '尚硅谷'
        }
        const cities = {
            xiaoqu: ['北京', '上海', '深圳']
        }
        Object.setPrototypeOf(school, cities);
        console.log(Object.getPrototypeOf(school));
        console.log(school);

18、ES6模块化

模块化是指将大的程序文件,拆分成有联系的小文件即模块

一、模块化优势

1、防止命名冲突

2、代码复用

3、高维护性

二、模块化规范产品

ES6之前js没有自己的模块规范化

ES6 之前的模块化规范有:

  1. CommonJS 规范=> NodeJS、Browserify
  2. AMD规范 => requireJS
  3. CMD规范 => seaJS

三、ES6模块化语法

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

⚫ export 命令用于规定模块的对外接口

⚫ import 命令用于输入其他模块提供的功能

四、实例

//./js/module1.js文件

 //export 对外暴露 school  和 teach()
 //分别暴露方式
export let school='xuexiao'
export function teach(){
    console.log("我可以教学生");
}

//./js/module2.js文件

let job="js开发"

function findJob(){
    console.log("找工作!!!");
}

//统一对外暴露
export {job,findJob}
//./js/module3.js
//默认暴露
export default{
    school:'xuexiao',
    change:function(){
        console.log("改变你");
    }
}

index.html

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

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script type="module">
        //1、通用导入方式
        //./index.html 文件
        //引入module1.js 取到所有export暴露数据(分别暴露) 存入module1 
        import * as m1 from './js/module1.js'
        console.log(m1);
        //引入module2.js 内容(统一暴露)
        import * as m2 from './js/module2.js'
        console.log(m2);
        //引入module3.js 默认暴露
        import * as m3 from './js/module3.js'
        console.log(m3); 
        m3.default.change();


        //2、结构赋值形式
        import {school,teach} from './js/module1.js'
        //重名时 可以使用别名,导入名称应和包内名称一致
        import {school as qinghua,findJob} from './js/module2.js'
        //默认暴露不可直接default
        import {default as module3} from './js/module3.js'
        console.log(school);
        console.log(teach);
        console.log(qinghua);
        console.log(findJob);
        console.log(module3);


        //3、简便形式 (只针对默认暴露)
        import mm3 from './js/module3.js'
        console.log(mm3);
    </script>
    <!-- 导入入口文件 -->
    <script src="./js/app.js" type="module"></script>

</body>

</html>

入口文件 ./js/app.js

//4、书写入口文件引入模块
import * as m1 from './module1.js'
import * as m2 from './module2.js'
import * as m3 from './module3.js'
console.log(m1);
console.log(m2);
console.log(m3);

五、模块化代码在项目中的使用方式

Bable转化

主要作用:将最新的ES6语法转化为浏览器可以识别的ES5语法

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

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <!--
        1、安装
         babel-cli babel命令行工具
         babel-preset-env 预设包包含最新es语法
         browserify 轻量打包工具,类似webpack
         输入命令安装:
             npm初始化:>npm init --yes
             安装工具:?>npm i babel-cli / babel-preset-env / browserify -d
        2、执行babel转换
            局部安装:>npx babel 源代码目录 -d 编译结果目录 --presets=babel-preset-env
            全局安装:>babel
        3、打包 
            针对模块化入口文件,否则无法正常引入
            >npx browserify 编译结果目录入口文件 -o 打包输出目录
            例子:>npx browserify dist/js/app.js -o dist/index.js
      -->
</body>

</html>

ES6模块化引入NPM包

二、ES7

/**
         * 1、Array.prototype.includes() 检测数组是否包含某个元素
         * 返回值  Boolean
         * /
         * 
        // const mingzhu = ['西游记','红楼梦','三国演义','水浒传'];
        //判断
        // console.log(mingzhu.includes('西游记')); //true
        // console.log(mingzhu.includes('金瓶梅')); //false

        /**
         * 2、   **  幂运算
         * 
        */
        console.log(2 ** 10); // ES7
        console.log(Math.pow(2, 10)); //ES5

三、ES8

1、async函数

作用:

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

特点:

1、async函数返回值为promise对象。

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

语法

 //async 函数(呃think)
        //特殊函数 总是返回promise对象 
        //声明方式:
        async function fn() {
            //返回值特点:
            //  返回的结果不是一个 Promise 类型的对象, 则就是成功 Promise 对象

            // 1、返回一个字符串 返回结果仍是成功状态的Promise对象
            //return '尚硅谷';


            // 2、return 返回一个成功的promise对象
            // return;


            // 3、抛出错误, 返回的结果是一个失败的 Promise
            // throw new Error('出错啦!');

            // 4、返回的结果如果是一个 Promise 对象
            return new Promise((resolve, reject) => {
                resolve('成功的数据'); //成功的promise对象
                //reject("失败的错误");
            });
        }

        const result = fn();
        console.log(result);

        //调用 then 方法
        result.then(value => { //成功时
            console.log(value);
        }, reason => { //失败时
            console.warn(reason);
        })

2、await表达式

特点:

1、await 必须写在 async 函数中

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

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

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

语法

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

        // await 要放在 async 函数中.
        async function main() {
            try {
                let result = await p;
                //await表达式只返回成功的Promise对象 失败会抛出异常
                console.log(result);
            } catch (e) {
                console.log(e);
            }
        }
        //调用函数
        main(); //失败啦!

async和await结合案例

1、结合读取文件

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

//读取『为学』
function readWeiXue() {
    return new Promise((resolve, reject) => {
        //读取 为学.md
        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);
        })
    })
}

//2、声明一个 async 函数
async function main(){
    //获取为学内容 promise对象
    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();
//运行指令 》 node 文件名.js

2、结合发送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();
        

3、对象方法的拓展

  1. Object.values()方法返回一个给定对象的所有可枚举属性值的数组
  2. Object.entries()方法返回一个给定对象自身可遍历属性 [key,value] 的数组
  3. Object.getOwnPropertyDescriptors()该方法返回指定对象所有自身属性的描述对象
 //声明对象
        const school = {
            name: "尚硅谷",
            cities: ['北京', '上海', '深圳'],
            xueke: ['前端', 'Java', '大数据', '运维']
        };

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

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

        // const obj = Object.create(null, {
        //     name: {
        //         //设置值
        //         value: '尚硅谷',
        //         //属性特性
        //         writable: true,//是否可写
        //         configurable: true, //是否可配置
        //         enumerable: true//是否可以枚举
        //     } 
        // });

js对象属性描述对象参考:

属性描述对象 – JavaScript 标准参考教程(alpha) (ruanyifeng.com)

四、ES9

1、对象的拓展运算符

 /**
        Rest 参数与 spread 扩展运算符在 ES6 中已经引入,不过 ES6 中只针对于数组,
        在 ES9 中为对象提供了
            像数组一样的 rest 参数和扩展运算符
        */
        //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: '天音波',
            f: '闪现'
        }

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

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

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

        console.log(mangseng)	

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

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

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

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

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


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

        const result = reg.exec(str);

        console.log(result.groups.url);

        console.log(result.groups.text);

3、正则拓展2:反向断言

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

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

3、正则拓展:dotAll模式

  //dot  .  元字符  除换行符以外的任意单个字符
        let str = `
        <ul>
            <li>
                <a>肖生克的救赎</a>
                <p>上映日期: 1994-09-10</p>
            </li>
            <li>
                <a>阿甘正传</a>
                <p>上映日期: 1994-07-06</p>
            </li>
        </ul>`;
        //声明正则
        // const reg = /<li>\s+<a>(.*?)<\/a>\s+<p>(.*?)<\/p>/;
        const reg = /<li>.*?<a>(.*?)<\/a>.*?<p>(.*?)<\/p>/gs;
        //执行匹配
        // const result = reg.exec(str);
        let result;
        let data = [];
        while(result = reg.exec(str)){
            data.push({title: result[1], time: result[2]});
        }
        //输出结果
        console.log(data);
	
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值