ES6简单学习

目录

接口调用

this关键字

变量声明

解构表达式

模板字符串

简化对象写法

箭头函数

函数参数默认值

rest 参数

spread 扩展运算符

 Symbol

迭代器

生成器函数声明与调用 

生成器函数参数

异步功能

Promise

读取文件

promise封装AJAX请求/接口调用

then方法-回调

promise 异步任务 回避回调地狱演示

catch 

Set 集合

集合使用案例

Map

Class类  对象

两种不同的类模板生成方式

静态成员

类的继承

get 和 set  对属性赋值

数值扩展

对象方法扩展

模块化

ES6 模块化语法

  babel对ES6模块化代码进行转换


接口调用

转下方promise 请求调用

this关键字

this是 JavaScript 语言的一个关键字。

它是函数运行时,在函数体内部自动生成的一个对象,只能在函数体内部使用。

function test() {
 this.x = 1;
}

        上面代码中,函数test运行时,内部会自动有一个this对象可以使用。

        那么,this的值是什么呢?

        函数的不同使用场合,this有不同的值。总的来说,this就是函数运行时所在的环境对象。        

        下面分四种情况,详细讨论this的用法。

        

情况一:纯粹的函数调用

这是函数的最通常用法,属于全局性调用,因此this就代表全局对象。请看下面这段代码,它的运行结果是1。

var x = 1;
function test() {
   console.log(this.x);
}
test();  // 1

情况二:作为对象方法的调用

函数还可以作为某个对象的方法调用,这时this就指这个上级对象。

function test() {
  console.log(this.x);
}

var obj = {};
obj.x = 1;
obj.m = test;

obj.m(); // 1

情况三 作为构造函数调用

所谓构造函数,就是通过这个函数,可以生成一个新对象。这时,this就指这个新对象。


function test() {
 this.x = 1;
}

var obj = new test();
obj.x // 1

运行结果为1。为了表明这时this不是全局对象,我们对代码做一些改变:


var x = 2;
function test() {
  this.x = 1;
}

var obj = new test();
x  // 2

运行结果为2,表明全局变量x的值根本没变。

情况四 apply 调用

apply()是函数的一个方法,作用是改变函数的调用对象。它的第一个参数就表示改变后的调用这个函数的对象。因此,这时this指的就是这第一个参数。

var x = 0;
function test() {
 console.log(this.x);
}

var obj = {};
obj.x = 1;
obj.m = test;
obj.m.apply() // 0

apply()的参数为空时,默认调用全局对象。因此,这时的运行结果为0,证明this指的是全局对象。

如果把最后一行代码修改为

obj.m.apply(obj); //1

运行结果就变成了1,证明了这时this代表的是对象obj

----------------------------------以上this的说明来自阮一峰的博客----------------------------

https://www.ruanyifeng.com/blog/2010/04/using_this_keyword_in_javascript.html

https://es6.ruanyifeng.com/#docs/intro 此网站是阮一峰ES6文档,可以当做字典使用

接下来的笔记来自尚硅谷ES6教程,本人为后端开发,前端还没摸着皮毛,笔记仅供

参考,详细教程建议学习阮一峰的ES6文档~

-----------------------------------------------------------------------------------------------------------

变量声明

let 关键字

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

        不允许重复声明

        块儿级作用域

        不存在变量提升

        不影响作用域链

        应用场景:以后声明变量使用 let 就对了

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

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

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

        //3. 不存在变量提升----变量提升指的是你没声明就用了 var是可以的 会给默认undefined值
        // console.log(song);
        // let song = '恋爱达人';

        //4. 不影响作用域链
        {
            let school = 'ES';
            function fn(){
                console.log(school);
            }
            fn();
        }

const 关键字

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

        声明必须赋初始值 标识符一般为大写

        不允许重复声明

        值不允许修改

        块儿级作用域

//声明常量
        const SCHOOL = '东北大学';

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

注意: 对象属性修改和数组元素变化不会出发 const 错误

应用场景:声明对象类型使用 const,非对象类型声明选择 let

解构表达式

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

ES6 允许按照一定模式从数组和对象中提取值,对变量进行赋值,
        这被称为解构赋值。
        1. 数组的结构
        const F4 = ['小沈阳','刘能','赵四','宋小宝'];
        let [xiao, liu, zhao, song] = F4;
        console.log(xiao);
        console.log(liu);
        console.log(zhao);
        console.log(song);

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

        let {name, age, xiaopin} = zhao;
        console.log(name);
        console.log(age);
        console.log(xiaopin);
        xiaopin();

        let {xiaopin} = zhao;
        xiaopin();

模板字符串

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

        字符串中可以出现换行符

        可以使用 ${xxx} 形式输出变量 

        

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

        2. 内容中可以直接出现换行符
        let str = `<ul>
                    <li>沈腾</li>
                    <li>玛丽</li>
                    <li>魏翔</li>
                    <li>艾伦</li>
                    </ul>`;
        3. 变量拼接
        let lovest = '魏翔';
        let out = `${lovest}是我心目中最搞笑的演员!!`;
        console.log(out);

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

简化对象写法

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

  let name = '老王';
        let change = function(){
            console.log('我们可以改变你!!');
        }

        const school = {
            name,
            change,
           // 用这种新的方法声明方法更加简单
            improve(){
                console.log("我们可以提高你的技能");
            }
        }

        console.log(school);

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

箭头函数

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

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

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


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

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

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

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

        2. 不能作为构造实例化对象
        let Person = (name, age) => {
            this.name = name;
            this.age = age;
        }
        let me = new Person('xiao',30);
        console.log(me);

        3. 不能使用 arguments 变量
        let fn = () => {
            console.log(arguments);
        }
        fn(1,2,3);

        4. 箭头函数的简写
            1) 省略小括号, 当形参有且只有一个的时候
            let add = n => {
                return n + n;
            }
            console.log(add(9));
            2) 省略花括号, 当代码体只有一条语句的时候, 此时 return 必须省略
            而且语句的执行结果就是函数的返回值
            let pow = n => n * n;
                
            console.log(pow(8));

箭头函数的注意点:

        如果形参只有一个,则小括号可以省略

        函数体如果只有一条语句,则花括号可以省略,函数的返回值为该条语句的执行结果

        箭头函数 this 指向声明时所在作用域下 this 的值

        箭头函数不能作为构造函数实例化

        不能使用 arguments

注意:箭头函数不会更改 this 指向,用来指定回调函数会非常合适

<div id="ad"></div>
    <script>
        需求-1  点击 div 2s 后颜色变成『粉色』
        获取元素
        let ad = document.getElementById('ad');
        绑定事件
        ad.addEventListener("click", function(){
            保存 this 的值
            let _this = this;
            定时器
            setTimeout(() => {
                修改背景颜色 this
                console.log(this);
                _this.style.background = 'pink';
                this.style.background = 'pink';
            }, 2000);
        });

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

        console.log(result);

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

    </script>

函数参数默认值

 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)
        }
        connect({
            host: 'atguigu.com',
            username: 'root',
            password: 'root',
            port: 3306
        })

rest 参数

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

arguments可以获取函数调用时候的所有实参        

作用与arguments相似


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

        rest 参数

        function date(...args){
            console.log(args);// filter some every map 
        }
        date('阿娇','柏芝','思慧');

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

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

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

spread 扩展运算符

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

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

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

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

应用

  1. 数组的合并 情圣  误杀  唐探
        const kuaizi = ['王太利','肖央'];
        const fenghuang = ['曾毅','玲花'];
        // const zuixuanxiaopingguo = kuaizi.concat(fenghuang);
        const zuixuanxiaopingguo = [...kuaizi, ...fenghuang];
        console.log(zuixuanxiaopingguo);

        2. 数组的克隆
        const sanzhihua = ['E','G','M'];
        const sanyecao = [...sanzhihua];//  ['E','G','M']
        console.log(sanyecao);

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

 Symbol

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

        Symbol 特点 :

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

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

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

        创建Symbol
        let s = Symbol();
        console.log(s, typeof s);
        let s2 = Symbol('尚硅谷');
        let s3 = Symbol('尚硅谷');  s3 ===s2 为false 


        Symbol.for 创建
        let s4 = Symbol.for('尚硅谷');
        let s5 = Symbol.for('尚硅谷');   s4=s5 为true 

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

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

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

        console.log(youxi)

symbol内置属性

除了定义自己使用的 Symbol  值以外,ES6  还提供了11 个内置的Symbol 值, 指向语言内部使用的方法。可以称这些方法为魔术方法,因为它们会在特定的场景下自动执行。

        Symbol.hasInstance

       --> 当其他对象使用 instanceof 运算符,判断是否为该对 象的实例时,会调用这个方法

        Symbol.isConcatSpreadable

        --> 对象的 Symbol.isConcatSpreadable 属性等于的是一个布尔值,表示该对象用于 Array.prototype.concat()时, 是否可以展开。

        Symbol.species

        --> 创建衍生对象时,会使用该属性

        Symbol.match  

        --> 当执行 str.match(myObject) 时,如果该属性存在,会 调用它,返回该方法的返回值。

        Symbol.replace

        --> 当该对象被 str.replace(myObject)方法调用时,会返回 该方法的返回值。

        Symbol.search

        --> 当该对象被 str. search (myObject)方法调用时,会返回 该方法的返回值。

        Symbol.split

        --> 当该对象被 str. split (myObject)方法调用时,会返回该 方法的返回值。

        Symbol.iterator

        --> 对象进行 for...of 循环时,会调用 Symbol.iterator 方法, 返回该对象的默认遍历器

        Symbol.toPrimitive

        --> 该对象被转为原始类型的值时,会调用这个方法,返 回该对象对应的原始类型值。

         Symbol. toStringTag

        --> 在该对象上面调用 toString 方法时,返回该方法的返 回值

        Symbol. unscopables

        --> 该对象指定了使用 with 关键字时,哪些属性会被 with 环境排除。

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

        let o = {};

        console.log(o instanceof Person);

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

迭代器

        遍历器(Iterator)就是一种机制。它是一种接口,为各种不同的数据结构提供统一的访问机制。

        任何数据结构只要部署 Iterator 接口,就可以完成遍历操作。

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

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

                Array

                Arguments

                Set

                Map

                String

                TypedArray

                NodeList

工作原理:

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

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

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

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

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

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

        使用 for...of 遍历数组
        for(let v of xiyou){
            console.log(v);
        }
        

        let iterator = xiyou[Symbol.iterator]();

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

生成器函数声明与调用 

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

代码说明:

         * 的位置没有限制

        生成器函数返回的结果是迭代器对象,调用迭代器对象的 next 方法可以得到

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

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

    //生成器其实就是一个特殊的函数
        //异步编程  纯回调函数  node fs  ajax mongodb
        //yield 语句函数代码的分隔符

        //生成器函数不能直接调用,使用举例
        function * gee(){
            console.log("输出");
        }
     //   gee().next();
        let  itt = gee();
        itt.next();

        function * gen(){
            // console.log(111);
            yield '一只没有耳朵';
            // console.log(222);
            yield '一只没有尾部';
            // console.log(333);
            yield '真奇怪';
            // console.log(444);
        }

        let iterator = gen();

        iterator.next();
        iterator.next();
        iterator.next();
        iterator.next();//每一次会执行一个log

        console.log(iterator.next()); //每一次会输出返回的结果  "一只没有耳朵" done :false(遍历是否完成)
        console.log(iterator.next());
        console.log(iterator.next());
        console.log(iterator.next());  //undefined  done:true

        //遍历
        // for(let v of gen()){ //会输出所有结果 111         一只没有耳朵 ....
        //     console.log(v);
        // }

生成器函数参数

    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 
        111  done :false
        BBB    第二个next的参数将作为 第一个 yield 的返回值 
        222  done :false 
        。。。

异步功能

 异步编程  文件操作 网络操作(ajax, request) 数据库操作
        1s 后控制台输出 111  2s后输出 222  3s后输出 333 
        回调地狱

        setTimeout(() => {
            console.log(111);
            setTimeout(() => {
                console.log(222);
                setTimeout(() => {
                    console.log(333);
                }, 3000);
            }, 2000);
        }, 1000);

        --

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

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

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

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

        调用生成器函数
        let iterator = gen();
        iterator.next();
 //模拟获取  用户数据  订单数据  商品数据 
        function getUsers(){
            setTimeout(()=>{
                let data = '用户数据';
                //调用 next 方法, 并且将数据传入
                iterator.next(data);
            }, 1000);
        }

        function getOrders(){
            setTimeout(()=>{
                let data = '订单数据';
                iterator.next(data);
            }, 1000)
        }

        function getGoods(){
            setTimeout(()=>{
                let data = '商品数据';
                iterator.next(data);
            }, 1000)
        }

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

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

Promise

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

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

        Promise.prototype.then 方法

        Promise.prototype.catch 方法

   //实例化 Promise 对象
        const p = new Promise(function(resolve, reject){
            setTimeout(function(){
                //
                // let data = '数据库中的用户数据';
                // resolve
                // resolve(data); 调用成功

                let err = '数据读取失败';
                reject(err);
            }, 1000);
        });

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

读取文件

使用 node + 文件全名调用js文件

//需要node环境  
//1. 引入 fs 模块
const fs = require('fs');
-----------------------------普通方法---------------------------

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


----------------------使用promise-------------------------------
//3. 使用 Promise 封装
const p = new Promise(function(resolve, reject){
    fs.readFile("./resources/为学.mda", (err, data)=>{
        //判断如果失败  改变promise对象p的状态  调用reject可以改变它的状态为失败,设置失败的值是err
        if(err) reject(err);  
        //如果成功  改变状态为成功,设置成功的值为data
        resolve(data);
    });
});
//由于promise是异步进行的,所以调用两个回调函数 看看promise的执行结果
// p.then 两个回调函数为参数, 回调函数中的参数 潜规则:建议写value和reason,成功调用第一个回调函数,失败调用第二个回调函数
p.then(function(value){
    console.log(value.toString());
}, function(reason){
    console.log("读取失败!!");
});
// 为什么使用promise  因为可以让代码不持续缩进,单个任务使用promise 没什么优势,但是多个异步任务可以不缩进代码

promise封装AJAX请求/接口调用

通过promise 将普通的Ajax请求封装起来,再通过回调函数判断成功或者失败,不会造成回调地狱~结构清晰~    不会在拿到数据的地方做数据处理,也就是普通AJAX成功或者失败的地方

处理数据 可以在回调函数处理数据,这样每个方法就有了明确的作用~

<script>
        // 接口地址: https://api.apiopen.top/getJoke   
        const p = new Promise((resolve, reject) => {
            //1. 创建对象   //整个就是用promise 将AJAX请求包起来,然后改变resolve和reject的状态判断成功或者失败
            const xhr = new XMLHttpRequest();

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

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

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

then方法-回调

  <script>
        //创建 promise 对象
        const p = new Promise((resolve, reject)=>{
            setTimeout(()=>{
                resolve('用户数据');
                // reject('出错啦');
            }, 1000)
        });

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

        const result = p.then(value => {
            console.log(value);
            //1. 非 promise 类型的属性
            // return 'iloveyou';
            //2. 是 promise 对象     ---成功或失败的状态由返回的promise对象 决定 与返回的promise对象相同
            // return new Promise((resolve, reject)=>{
            //     // resolve('ok');   //同样可以写同步任务
            //     reject('error');
            // });
            //3. 抛出错误
            // throw new Error('出错啦!');  状态 为reject  值为 出错啦!
            throw '出错啦!';       和上面相同
        }, reason=>{
            console.warn(reason);
        });

        链式调用    ----由于then返回的是一个 promise对象 所以返回的对象同样可以调用then方法, 

then的回调可以只写成功的回调方法,失败的回调方法可以不写
        p.then(value=>{

        }).then(value=>{

        });


    </script>

promise 异步任务 回避回调地狱演示

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

catch 

只有then 没有catch也可以~,也可以then只写成功的回调,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 集合

        和Java一样,不可重复,自动去重~

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

        size 返回集合的元素个数

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

        delete    删除元素,返回 boolean 值

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

        clear    清空集合,返回 undefined

<script>
        //声明一个 set
        let s = new Set();
        let s2 = new Set(['大事儿','小事儿','好事儿','坏事儿','小事儿']);

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

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

集合使用案例

<script>
        let arr = [1,2,3,4,5,4,3,2,1];
        //1. 数组去重
        // let result = [...new Set(arr)];
        // console.log(result);
        //2. 交集
        let arr2 = [4,5,6,5,6];
        // let result = [...new Set(arr)].filter(item => {
        //     let s2 = new Set(arr2);// 4 5 6
        //     if(s2.has(item)){
        //         return true;
        //     }else{
        //         return false;
        //     }
        // });
        // let result = [...new Set(arr)].filter(item => new Set(arr2).has(item));
        // console.log(result);

        //3. 并集
        // let union = [...new Set([...arr, ...arr2])];
        // console.log(union);

        //4. 差集
        let diff = [...new Set(arr)].filter(item => !(new Set(arr2).has(item)));
        console.log(diff);

    </script>

Map

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

        size    返回 Map 的元素个数

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

        get    返回键名对象的键值

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

        clear    清空集合,返回 undefined

 <script>
        //声明 Map
        let m = new Map();

        //添加元素
        m.set('name','哔哩哔哩~');
        m.set('change', function(){
            console.log("我们可以改变你!!");
        });
        let key = {
            school : '哔哩哔哩ST'
        };
        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);

    </script>

Class类  对象

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

        知识点:

        class 声明类

        constructor 定义构造函数初始化(没有构造函数也是合法的,可以没有属性)

        extends 继承父类

        super 调用父级构造方法

        static 定义静态方法和属性

        父类方法可以重写

两种不同的类模板生成方式

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

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

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

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

        console.log(onePlus);
    </script>

静态成员

 <script>
        // 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);
-------------------------------------------------ES6------------------------
        class Phone{
            //静态属性
            static name = '手机';
            static change(){
                console.log("我可以改变世界");
            }
        }

        let nokia = new Phone();
        console.log(nokia.name);//undefined  
        console.log(Phone.name);
    </script>
不管是ES5 还是6   静态属性都属于类调用,不属于具体的对象

类的继承

和Java类似

<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);// 调用父类的构造方法~和Java类似
                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>

get 和 set  对属性赋值

注意这里的price 是属性!

<script>
        // get 和 set  
        class Phone{
            get price(){
                console.log("价格属性被读取了");
                return 'iloveyou';
            }//当price属性被调用了,这个price函数就会调用,return的值,就是price的值

            set price(newVal){
                console.log('价格属性被修改了');
            }//同理,当price被设置值,会调用set方法,主要用于判断给price设置的值是否合法~
        }

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

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

数值扩展

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

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

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

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

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

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

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

    </script>

对象方法扩展

 <script>
        //1. Object.is 判断两个值是否完全相等 
        // console.log(Object.is(120, 120));// === 
        // console.log(Object.is(NaN, NaN));// === 
        // console.log(NaN === NaN);// === 

        //2. Object.assign 对象的合并
        // const config1 = {
        //     host: 'localhost',
        //     port: 3306,
        //     name: 'root',
        //     pass: 'root',
        //     test: 'test'
        // };
        // const config2 = {
        //     host: 'http://bilibili.com',
        //     port: 33060,
        //     name: 'bilibili.com',
        //     pass: 'iloveyou',
        //     test2: 'test2'
        // }
        // console.log(Object.assign(config1, config2));// 用2的属性 覆盖第一个  1有2没有的属性不会变化,2有1没有的属性,1不会变化

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


        
    </script>

模块化

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

        模块化的好处:

                防止命名冲突

                代码复用

                高维护性

        模块化规范产品:

        ES6 之前的模块化规范有:

                1) CommonJS => NodeJS、Browserify

                2) AMD => requireJS

                3) CMD => seaJS

ES6 模块化语法

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

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

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

export 举例

js文件:

//分别暴露
export let school = '哔哩哔哩';

export function teach() {
    console.log("我们可以教给你开发技能");
}

-----------------------m2文件--------------------
//统一暴露
let school = '哔哩哔哩';

function findfriend(){
    console.log("我们可以帮助你找机油!!");
}

//
export {school, findfriend};


--------------------------m3----------------------------

//默认暴露
export default {   //{里面可以是一个任意内容,字符串,数字等,对象居多}
    school: 'BLBL',
    change: function(){
        console.log("我们可以改变你的取向!!");
    }
}

html文件: 

 <script type="module">
        1. 通用的导入方式
        引入 m1.js 模块内容
        import * as m11 from "./src/js/m1.js"; //*将所有暴露的类容导入m11这个对象
        //引入 m2.js 模块内容
        import * as m22 from "./src/js/m2.js";
        //引入 m3.js 
        import * as m33 from "./src/js/m3.js";  //m3 是默认暴露,如果要调用m33中的方法
//需要多调用一层default-----》m33.default.method()

        2. 解构赋值形式
        import {school, teach} from "./src/js/m1.js";
        import {school as bilibili, findfriend} from "./src/js/m2.js";//school重名了 使用别名
        import {default as m3} from "./src/js/m3.js";//不能直接使用default  要使用别名~

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

另一种引入方式:

项目中一般不会这样引入,因为有的浏览器不支持ES6~!!

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

入口文件app.js

//入口文件

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

  babel对ES6模块化代码进行转换

不是所有浏览器都对ES6支持~!!

略!

 <!-- 
        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
     -->
     <script src="dist/bundle.js"></script>

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值