Es6语法


1.let和const声明变量

当时用var进行声明变量时,会出现变量提升的问题: 
console.log(b); //undefined var b = 100    arr = []; for (var i = 0; i < 10; i++) { arr[i] = function () { return i } } console.log(arr); // [?, ?, ?, ?, ?, ?, ?, ?, ?, ?] 10个函数的数组 console.log(arr[5]()); // 取到的值是10,正常应该是5才对。 这就是变量提升! 为什么?因为在执行var进行变量声明时出来了变量提升。i被提升到全局作用域中,i就被赋值为循环后的最后结果10。 怎么解决?使用let去声明就不会出现这个问题 1.let 声明变量:   1.他是一个变量声明方法   2.是一个块级作用域,相当于类中的类变量,只能被类中的方法和对象使用。   3.let 声明的变量不能重复情况,不能被覆盖 报错 console.log(b); //打印报错 let b = 100 let a = 10 let a = 100 conlost.log(a) // 报错a重复出现 2.const 变量声明:   1.是一个变量的方法   2.是块级作用域   3.不能重复声明   4.声明后不能修改 const a = 100 a = 1000 // 无法重新赋值,报错 const p = {   name:'xxx',   age : '18' } // 不能直接修改p这个对象,但是可以修改p内部的值 p.age = 20

2.模板字符串的语法




结果:
    
  • xxx

3.Es6的函数与Es5的区别

1.带有参数的模板值函数

es5写法
function add(a, b) {
    
      a = a || 10, // 使用双管道符 或的方式进行声明默认值
      b = b || 10
    
    return a+b
}    
            
es6写法
function add(a = 10, b = 20) {  // 带默认参数
     return a + b
}


2.默认表达式
es6 默认知可以为一个函数对象
   function add(a,b=date(5)){ // b默认值需要等到b函数执行完毕后
        return a+b
    }
    function date(val){
        return 5 + val
    }

4.运算符  

1.剩余运算符。
可以将在函数中剩余的参数进行获取
es5:

  function pick(object) {
      let res = Object.create(null)  // 创建一个没有任何方法的对象
      for (let i = 1; i < arguments.length; i++) {
     // arguments 对象: 是一个对应于传递给函数的参数的类数组对象
     res[arguments[i]] = object[arguments[i]] // 进行对传入的对象进行赋值
}
    return res
}
//创建一个对象
   let book = {
         title: '1231',
         author: "65465",
         year: 2019,
     }
let bookdata = pick(book, 'title', 'author',"year") // 将值传入进行取
console.log(bookdata) //


es6:
剩余运算符写法 使用...key(key可以随便那个定义都可以)
 function pick(object, ...key) { // ...key 返回一个数组
        console.log(key)  // ...key 接受到 传入'title', 'author', "year"3个名称

        let res = Object.create(null)
        for (let i = 0; i < key.length; i++) {
            res[key[i]] = object[key[i]]
        }
        return res
    }

// 声明对象
 let book = {
        title: '1231',
        author: "65465",
        year: 2019,
    }
let bookdata = pick(book, 'title', 'author', "year")
console.log(bookdata)
// 剩余运算符相当于,将除了固定值以外的内容全部接受了,返回一个数组(与python中的args和kwargs相同)

2.扩展运算符
将数组进行分割为一个一个的

es5写法
const arr = [11,22,33,44,566,778979,9879] //数组

//获取 数组中最大的值
console.log(Math.max.apply(null,arr)) 

const add = Math.max(11,22,33,45646,4654,6,) // 将值传入进行获取最大值
console.log(add)


es6:
// 直接将数组中的每一个值进行分离传入max函数中进行对比取出来最大的值
console.log(Math.max(...arr))
而这个扩展运算符相当于 *args 与 **kwargs 差不多

5.箭头函数

es6中的箭头函数取代了匿名函数
取代function(){} 等价于 ()=>{} 匿名函数

例如:
        let add = function (a, b) {
            return a + b
        }
        console.log(add(10, 20))  // 获取结果就是30

        es6的方式(多个参数的情况下) 箭头函数相当于 将function给替代为 => 
        let add = (a,b) => {
            return a + b
        }
        console.log(add(10,20)) // 获取的结构 也是30 

另一种写法

let add = (a,b) = > a+b


箭头函数中参数问题:

带一个参数:
let add = (a)=>{
     return a+10  
}

各种写法
let add = val =>val; //这中情况相当于
let add = val => (val+5) //这中情况相当于
let add = val => { return val + 5 } //这中情况相当于


没有参数的情况下
        // 没有参数的情况下 前面的小括号必须写
        let add = () =>{return 'hahahh'}
        console.log(add())

箭头函数返回对象
  let add = () =>{
    return 
    {id:1,
    name:'123'   
    }

}
简写:
let add = id =>({id:1,'name':1233})



// 关于闭包函数
es5闭包:
        let fn = (function(){
           return function(){ 
               return 123 // 将123 参数返回给了function匿名函数
           } 
        })() // 第一层函数执行,获取到的第二层的function函数(没有执行) 需要执行
        fn(); // 执行内层的函数

es6箭头函数闭包
        let fn = (() => {
            return () => {
                return123
            }
        }) (); // 第一层函数执行,获取到的第二层的function函数(没有执行) 需要执行
        fn(); // 执行内层的函数

         

6.箭头函数的this指向问题  

es5的this指向

        // es5 中的this指向:取决于调用该函数的上下文对象
        let pa = {
            id : 10,
            init:function(){
                // 添加一个click事件
                //document.addEventListener 给文档设置一个点击事件,当点击文档中的任何一个位置,就会出发内部函数
                document.addEventListener('click',function(){
                        console.log(this); // this指向了 document文档对象
                        this.doSomeThings(event.type) // event.type打印 绑定类型 传入函数doSomeThings
                        console.log(event.type) // 类型打印的时 click点击事件
                }.bind(this),false) //设置bind方法 将this指向 pa 对象 //就会执行doSomeThings函数
            },
            doSomeThings:function(type){
                console.log(`事件类型${type},事件id${this.id}`)
            }

        }
        pa.init()


es6中的this执行

        //es6 解决this指向问题 // 使用=> 就会找上层的作用域
        // 箭头函数之后没有this指向,通过查找作用域进行找 
        //   一但使用箭头函数,当前有没有作用域,就找上层的作用域
        // 3层作用域    this
        let pa = {
            id : 10,
            // 2级作用域 this
            init:function(){  
                // 1级作用域 this
                document.addEventListener('click',(event)=>{
                        // console.log(this); 
                        this.doSomeThings(event.type) 
                        // console.log(event.type) 
                },false)
            },
            doSomeThings:function(type){
                console.log(`事件类型${type},事件id${this.id}`)
            }

        }
        pa.init()


        // 怎么查找作用域
        // 在 document.addEventListener方法定义的内部是一个作用域
        // 这个作用域上层指向了 init:function init变量
        // init 变量的上层作用域 指向了对象pa 所以 this指向pa对象
    
        // 假设 int:function  定义为箭头函数 => 那么相当于 init没有作用域,就会找到pa对象的作用域
        // 在找到window 作用域练 最外层


使用箭头函数的注意事项:
1.使用箭头函数就会内部就没有 arguments 方法,因为使用箭头函数就没有作用域链,就会指向weindow
2.不能使用new进行创建箭头对象,因为箭头对象没有作用域

7. 解构

// 解耦语法是一种对运算的一种扩展
// 主要针对 数组和对象操作
// 优点:优化代码和易读性

1.针对完整的对象
        let info = {
            type: 'id',
            name: ' askjh'
        }

es5获取对象中的值   
let type = info.type
let name = info.name


es6解构语法
let { type, name } = info

2.针对不完全解构 可以忽略某些属性
let obj = {
             a: {
                name: '张三'
             }, // 对象
             b: [], // 数组
             c: 'hello world'
}

let {a} = obj // 获取obj对象中的a对象

也可以使用剩余运算符进行获取剩下的值
let {a,...key} = obj
key : {b: Array(0), c: 'hello world'}

3.使用解构进行默认值赋值
let {a,b=30} = {a:40} // 设置b的默认值为30 a赋值为40

进行数组的复制
let arr = [1,2,3]
let [a,b,c] = arr
结果:123

嵌套结构:
// 相当于python 中的 a,b = 1,3 但是需要根据对应参数的形式获取值
let [n,[d],e] = [1,[2],3]  //1 2 3

8.对象与数组的扩展 

1.对象的扩展
关于写入:
const name=12, age=12

es5写法
const pe = {
name:name,
age:age
//写入函数
sayName:function(){}
}
函数中的参数:
function add(x,y){
return{x:x,y:y}

}


es6写法
const pe = {
name,
age
//写入函数
sayName(){} // 只写省略了function
}

function add(x,y){
return{x,y}
}


es6的其他:
set 与 get 方法

当直接执行get 方法就会根据默认值执行  就会直接执行get
当执行set是会优先执行set方法,在执行get方法

let add= {
 wheel:4 ,

// 在调用 get方法执行时,就会先执行这个方法进行判断
 set(val){
    if (val < this.wheel){
                 throw new Error('数量太少') // throw 抛出异常
               }
    },
 get(){ // 等待set方法执行完毕后才会执行
     return this.wheel
   }     
}
caet.set(3) // 对方法传入3时,在执行 get 就会获取set值的判断结果
console.log(caet.get()) // 如果不对set传入值,那么默认就会参数就是wheel

es6属性表达式

const obj = {} 
obj.isshow = true // 对obj对象进行赋值
const name = 'a'
obj[name+'bc'] = 123 // 将name变量 和 bc 进行拼接进行写入对象中

结果:{isshow: true, abc: 123}

写入函数对象
obj['f'+ 'cc'] = function(){
 console.log(this);
}
结果:{isshow: true, abc: 123, fcc: ?}

对象的其他方法2
is() 相当于 ===  比较与两个值是否严格相同
console.log(NaN === NaN); //  不严谨 false
console.log(Object.is(NaN,NaN));  // true

assign() 对象的合并 属于浅拷贝
let t={}
let b={a:2}
Object.assign(t,b) // 将b中的值写入到t对象中 获取一个新的对象
console.log(t) // {a: 10}


2.数组扩展

数组的方法:from 与 of
from 可以 将伪数组转换为真正的数组
数组的 of 将一组的值转换为数组 任意的数据类型转换为数组

es5:
function add(){
arguments //是一个伪数组对象
let arr = [].slice.call(arguments)
console.log(arr) // es5方法直接转换为一个真的数组
}

es6 中的from
function add(){
arguments //是一个伪数组对象
 let arr = Array.from(arguments); //直接调用form方法转换
console.log(arr) 
}
from的第二个参数:
let lis = document.querySelectorAll('li') // 获取全部的li标签
// 第二个参数是一个回掉函数处理转换的数组中的元素
// ele 接受每一个 li标签  在获取ele.textContent 标签中的文本
let list = Array.from(lis, (ele) => { return ele.textContent })
变成数组并且获取了li标签中的值


es6中的of
console.log(Array.of(3,1,2,4,5,6,7,88,9)); //[3, 1, 2, 4, 5, 6, 7, 88, 9]

es6数组中的copywithin()方法
复制替换将数组中的值进行替换 返回当前的数组
let a = [1, 2, 3, 4, 5, 6].copyWithin(0, 3) // 原结果[1,2,3,4,5,6]
将0-3的数替为4-5 因为顾前不顾后
console.log(a); // [4,5,6,4,5,6]

es6数组中的findindex()方法 find查找数值
find查找数值:获取数值 第一个符合条件的
findindex()方法:获取数值的下标索引 第一个符合条件的

[1, 2, -103, 4, 5, -10, 7].find((n) => { // n就是遍历数组的每一个值
     return n < 0
}

[1, 2, -103, 4, 5, -10, 7].findindex((n) => { // n就是遍历数组的每一个值的下标
     return n < 0
}


es6数组的
entries(对键值对遍历) keys(对键的遍历) values(对值的遍历) 返回一个遍历起  可以使用for ... of 进行遍历

与python中的items keys values 相同

key 取索引
let a = [1, 2, 3, 4, "a", 6].keys()  // a是一个遍历器
console.log(a); // 获取的结构 就是一个遍历器Array Iterator
可以使用for ... of进行遍历
  for (let index of a) {
            console.log(index)  
        }

value取值
let b = [1, 2, 3, 4, "a", 6].values()
for (let index of b) {
            console.log(index) 
        }

entries() 取值和索引
let c = [1, 2, 3, 4, "a", 6].entries()
for (let [key, val] of c) {
            console.log('这是键', key) // 获取索引
            console.log('这是值', val)  // 获取值
        }


includes 返回一个bool值 表示一个数组是否包含这个值
console.log([1,2,3,4].includes(2)); // true
console.log([1,2,3,4].includes(10)); //false

9.es6新数据类型  

新的数据类型
// 原始数据 symbol ,表示他他是一个独一无二的值
const name = Symbol('name') // 内存地址不一样
const name2 = Symbol('name') // 独一无二的一个值

虽然值相同,但是内存地址不同,独一无二的
console.log(name === name2); //false 

symbol可以设置私有属性
注意:
//用来定义对象的私有变量// 可以设置对象的私有的属性
//如果使用symbol声明的变量 在取值时 一定要用[]取值
// 无法进行for遍历

let s1 = Symbol('name')

let obj = {
    [s1] : '123' // 存值
}
obj[s1] //取值

//两种方式 symbol声明的属性名(作为对象的key)
Object.getOwnPropertyDescriptor(obj)[0] // 获取值

Reflect.ownKeys(obj)


1.es6的set集合类型
先创建一个set的类型
let set = new Set() //打印后获取的结果是:Set(0) {size: 0} size表示集合的长度
//set 表示一个无重复值的有序列表 不能重复 无法被释放的类型

set.add(值) // 可以添加数值 集合 对象 字符串 布尔值
set.delete(值) // 删除
set.has(值)  // 查看当前值是否存在 返回flase true
set.size() // 访问集合的长度

将set类型转为数组
let set2 = new Set([1,2,3,4,4,5,66,44]) // 集合将元素中的数组进行重复的剔除
let arr = [...set2] // 使用扩展用算符进行转换为数组

2.es6的map键值类型
map类型是键值对的有序列表,键和值的任意类型 无法被释放

        // 声明 map
        let map = new Map();
        // 进行设置值
        map.set("name", '张三')  //Map(1) Map(1) {'name' => '张三'}
        //循环遍历 key :name val:张三
        console.log(map) // Map(0) { size: 0 } 打印的结构

        // 获取值
        console.log(map.get('name')); // 张三

        // 校验值
        console.log(map.has('name')) //  true

        //删除值
        console.log(map.delete('name')) // 删除后 打印的结果也是 bool类型

        // 清除值
        map.clear()  //清空值
    
      
        // 因为这个map结构使数任何类型  key val 可以使任意结构
    
        map.set([11, 2, 3, 44, 5, 6,], 'hello') //{Array(6) => "hello"} 数组: 字符类型
        console.log(map);
        // 设置多元数组
        let m = new Map([["a", 1], ["b", 2]])
        console.log(m) // {'a' => 1, 'b' => 2}

10.迭代器

// 迭代器,一种新的遍历机制

const item = ['1',2,55,'asd'] // 设置一个数组类型

let func = item[Symbol.iterator]() // 获取数组走的迭代器
//返回一个函数 ? values() { [native code] }

 console.log(func.next()) // {value: '1', done: false} 
// 返回的一个对象 value代表时数组中的值 done false 代表是遍历还没有完成 当done为true时,说明便利完成
console.log(func.next())
 // {value: undefined, done: true} done为true 说明为遍历完成 value变为 空

/ 迭代器两个核心:
    // 1 迭代器是一个接口,能快捷的访问数据  [Symbol.iterator]( 创建迭起,同给迭代器的next的结果
    // 2 迭代器遍历数据结构的指针 第一次调用指向了 1  value指向 1 dome为false 以此类推 
    // 当done 为true时,遍历结束 

11.生成器

1.命名生成器

function* func(){
     // 这样定义函数就可以使用yield关键字
      yield 
    
}
const ite = func()   // 这个就是迭代器对象

案例:
创建生成器
        function* func(){
            let res = yield request('传入的网络地址') // 3.当执行这个迭代第一次时,会执行request函数
            
//res :res 是谁:恢复执行传入next(实参)
        }    

        const ite = func()  //1. 这个就是迭代器对象
     
        ite.next() // 2.恢复yield进行执行 执行这个生成器函数 就会执行 yield中的关键字


        function request(url){
            $.ajax({
                url:url,
                method:'get',
                success(res){ //执行这个回调函数,在执行yield时会将res传给上一个执行yield 中的变量
                    ite.next(res) // 4.恢复执行并且 将res传入给 生成器值的变量res    
                }
            })
        } 




案例二
 function* en(){
            add() // 执行第一个开始加载提示
            yield del() // 卡在加载提示这里,当加载提示执行
            func()
        }
        const ite = en() // 生成器对象
        ite.next() // 执行第一次
        function add(){
            console.log('开始加载... 图片');
        } 


        function func(){
            console.log('隐藏加载提示...显示图片')
        }

        function del(){
            //  setInterval计时器
            setTimeout(() =>{
                console.log('加载完成,隐藏加载效果')
                // 加载提示执行后执行
                // 执行生成器中的下一次next方法
                ite.next() // 执行第二次
            },5000)
            
        }

12.生成器generator函数

generator 函数 可以通过yield关键字 将函数挂起,为了改变执行流程提供了可读性
为异步编程(解决异步代码)
generator 函数是分段执行,yield语句是暂停执行,next就是恢复执行
//区别
1.function后  函数名前 * 
2 只能在函数内部使用yield表达式 让函数挂起

        function* func(){
            yield 1; // 当使用yield关键字时,就会在这个位置挂起不走,当使用next才会执行
        }
        // 返回一个遍历器对象, 可以调用next()方法调用
        let fn = func() // 返回一个对象给 fn变量 返回遍历器对象
        // 使用next()方法 // 可以.value取值 done 获取状态(false还可以next true不能next)
        console.log(fn.next().done); //打印的结果就是 {valse:1 ,done:false}
        // 当第一次调用next 就会卡在第一个yield


对迭代器传入值:
传入的参数将值给到了执行完毕的 yield中

// 对迭代器的传值
        function* add(){
            console.log('hehehe');
            // x 不是 yield 2 的返回 是当前next 调用 恢复调用yield执行传入的实参
            let x = yield "a" // 当使用next时 卡在这个位置
            console.log('hahah',x);
            let y = yield '123'
            console.log('hahahz',y);
            return x+y
        }
        let fn = add()
        // 先打印 log 中的数据  在进行打印yield关键字中的内容,函数进行挂起
        // 在进行执行next 时就恢复执行
        console.log(fn.next(10)); // {value: 'a', done: false}

        // 当进行传值时,这个next的值传给乐 let 中的x
        //  hahah 20
        console.log(fn.next(20));  // {value: '123', done: false}

        // 当进行传值时 next  中的参数传给y值
        // 返回值return x+y找到下一个执行的yield 中的 对value进行赋值,因为最后一次执行done: true
        // 所以就赋值到最后一个next 的value中
        console.log(fn.next(20)); //{value: 40, done: true}



主要作用就是 不具备 interator 接口的对象提供的遍历操作


// 将不具备 interrator循环的对象 变为可遍历操作
        function* func(obj) { // 生成器写法 + yield 挂起
            const propkey = Object.keys(obj) // 传入的对象 返回一个迭代器
            console.log(propkey);
            for (let p of propkey) { // 迭代器就可以进行for of循环
                yield [p, obj[p]] // 构造结构 {name:1223}  // 使用yield关键字函数挂起
            }
        }


        const obj = {
            name: 133,
            age: 456
        }



        console.log(obj); // {name: 133, age: 456} 普通的对象

        for (let [key, val] of func(obj)) {
            console.log(key, val);
            console.log(`${key}:${val}`)
        }

13.promise的使用

1.基本知识:

是一种异步的解决方案: 中文名为承诺
promise 相当于一个容器,放置这未来要执行的事件(异步)的一个结果
各种异步操作都可以使用同样的方式进行处理 axios库就是基于promise

特点:
1. 对象的状态不收外接影响 异步处理的状态: peendig(进行中) resolved(成功) rejected(失败了)
这三个状态 保存在peomise
2.一旦改变,就会在变,任何时候都可以 得到结果 进行中- 成功  进行中-失败 都存储在peomise

怎么使用:
1.创建一个promise对象接受回调函数
new Promise(接受一个回调函数) 
回调  函数接受两个参数:rejected,resolve 成功和失败(固定写法)
例如:
案例伪造异步操作:
  let pro = new Promise(function (rejected, resolved) {
            // rejected,resolve 这个参数都是方法
            // 执行异步操作
            let res = {
                code: 200,
                data: {
                    name: '成功了'
                },
                error: '失败了'
            }
            // 伪造异步操作
            // 使用setTimeout方法定时伪造异步
            setTimeout(() => {
                if (res.code === 200) { // 如果状态为200
                    resolved(res.data) // 就将成功的值传给resolved成功状态 可以pro对象中的then() 获取成功的值
                } else {
                     rejected(res.error)
                }
            }, 1000)



//pro.then() // 成功的结果 执行异步操作的成功的结果 内部接受一个回调函数
val接受的就是成功状态的值
获取存在成功状态下的内容  使用then方法获取成功返回的内的成功信息和错误新
pro.then((val) => { // 接受回调函数
            // val 接受成功的数据
            console.log(val); //val 接受的是请求成功状态下的data中的错误值和成功值
        }, (err) => { // 接受异步请求中请求状态 错误的内容
            console.log(err) // 获取请求失败状态下的错误值
        })


// 封装异步操作
// ex 接受时间
// 封装了promise 方法,变得更为灵活
        function time(ex) {
            return new Promise((rejected, resolved) => {
                setTimeout(() => {
                    resolved('成功的信息')
                }, ex);
            })
        }
        time(1000).then((val) => {
            console.log(val)
        })

promise的封装ajax请求

        //pormise 封装一个ajax 异步请求

        const getJSON = function(url){
            //在这个方法中封装一个promise对象
            new Promise((reject,resolve)=>{
                // 创建一个请求
                const xhr = new XMLHttpRequest()
                //打开对象
                xhr.open('GET',url)
                // 设置状态 回调函数
                xhr.onreadystatechange = handler
                //约定返回数据类型
                xhr.responseText = 'json'
                //设置请求头
                xhr.setRequestHeader('Accept','application/json')
                //发送
                xhr.send() // get必须写
                // 回调函数
                function handler(){ // 创建回调函数
                // this指向 xhr对象
                    console.log(this.readyState) // 获取数组的状态
                    if(this.readyState === 4){
                        if(this.status === 200){ // 后端请求的状态
                              resolve(this.response) // 获取的请求体返回  
                        }else{
                            reject(new Error(this.statusText)) // 讲请求状态的error
                        }
                    }
                }
            })
        }


        getJSON('url') // 传入地址
        .then((val)=>{
            console.log(val)
        },(error)=>{
            console.log(error);
        })

        //其他pormise中的其他方法
        //then() 方法 第一个参数:relove 回掉方法 第二个参数:可选的reject 状态的回调 
       // then() 返回了什么:返回的时新的pormise实例对象 还可以.then()  可以采用链式写法
       // 可以特殊写发 链式写法
        getJSON('url').then(val=>{
            // 返回正确的操作
       }).catch(err=>{
            // 返回错误的操作
       })

promise的其他

 // resolve() reject() all() race() finally() 方法


1.resolve()  方法: 与reject()相同效果
可以其他转换为 promise对象 现有的任何对象转换为
let p = Promise.resolve('foo') //将字符串foo转为promis对象 
//等价于
 let p = Promise(resolve => {
        return resolve('foo')
 })  直接返回foo


console.log(p);
p.then((val) => {
console.log(val); // 结果就是 foo
})

2. all() 并行的执行3个异步
all() 并行的执行这个3个异步 // 一起操作 游戏素材 加载
        let p1 =new Promise((resolve,reject)=>{}) 
        let p2 =new Promise((resolve,reject)=>{}) 
        let p3 =new Promise((resolve,reject)=>{})    

        let lst = [p1,p2,p3]
        let p4 = Promise.all(lst) // 传入一个数组
        p4.then((val)=>{
            // 3个都成功才是成功
        }).catch((err)=>{
            // 如果一个失败 就全失败
        })

3.catch()方法 获取请求失败后的信息
        // 请求图片资源
        function img(imgs) {
            return new Promise((resolve, reject) => {
                new imgg = new Image() // Image()函数
                img.onload = function () {
                    resolve(img) // 成功返回img
                }
                img.src = imgsrc
            })
        }
        // 请求图片时长
        function timeout() {
            let p = new Promise((resolve, reject) => {
                setTimeout(() => {
                    reject('请求超时')
                }, 3000) // 设置时长3秒
            })
        }
        // 参数接受数组 请求成功不会走catch
        Promise.rece([img('images/2.peg'), timeout()]).then(res => {
            console.log(res); // 如果3秒内请求图片就会执行这里
        }).catch(err=>[ ///*****
            console.log(err) // 如果3秒后才能请求到就会执行请求超时(打印请求超时提示)
        ])

// race() finally(()=>{也是一个回调函数}) 不论是promise对象请求数据成功失败 都会执行race() finally()这两个方法

14.async异步

        // 使用async 进行异步操作 / 返回一个promise对象 可以统括then 和catch
        // async 时gemerator 的一个语法糖
            async function f(){
                // 这个后台的字符串会被async方法转换为 promis对象
                // 字符传会被转换为promis对象
                // await命令就是等待
                // return await 'await(等待,必须使用async才能使用await命令)等待命令'


                //解释版
                let s = await '你好 你好 async' //1.s变量执行
                let data = await s.split('') // data 等待s变量执行完毕后 在进行执行
                return data // 最终返回的时data等待执行后的结果
            }

            //console.log(f()); // Promise {: undefined} 返回一个promise对象
           f().then((val)=>{
            console.log(val); //val 就会接受到await 和后面的字符串信息
           }).catch((err)=>{
               console.log(err);
           }) 

           // 假如:async函数中有多个await 那么then函数等待 所有的await指令 运行完毕的结果 才会执行then

解决只有执行await后的才能返回解决 

使用try 就算await出现错误,也可以获取正确的结果           
//错误的状态下的异步
           async function f2(){
               // throw 抛出错误对象
               // throw new Error('出错误了!!!')

                //await '后面必须是一个promise对象,不管是什么类型都会转换为promise对象'

                // await 特点就是 如果一个出错执行了错误信息,下面的await不会执行


                // await Promise.reject('出错了') // 只会打印出错了,下面的命令就不会执行
                // await Promise.resolve('正确的')

                // 解决await 出现错误不执行的弊端
                try {
                    await Promise.reject('出错了') // 就算出错
                }catch(err){

                }
                return await Promise.resolve('正确的') // 还是可以出现正确的
           }
           // catch 接受报错信息
           f2().then((val)=>{console.log(val);}).catch((err)=>{console.log(err);})

15.class类的使用 

1.类的创建
es5构造类

    // 这是一个类
    function pe(name,age){
        this.name = name
        this.age = age
    }
    // 每个函数都有一个prototype属性,这个属性是指向一个对象的引用,这个对象称为原型对象,
    //原型对象包含函数实例共享的方法和属性,
    // prototype每个函数都有的一个特点,指向一个应用对象,在对象中有共享的构造方法和属性
    pe.prototype.pp = function(){ // 类里面的方法,可以更加创建的对象进行调用
        return [this.name,this.age]
    }
    // 利用pr函数对象内的prototype方法构造一个 pp的公共方法
    
    let p1 = new pe('123','3456') // 创建一个pe类的对象,就可以获取内部的方法
    console.log(p1.pp()); // ['123', '3456'] 就可以根据这个对象调用内部的方法



es6构造类
    class Person{ // 使用class类
        // 创建对象立即被调用
        constructor(name,age){ //constructor 这是一个初始化方法,创建类对象时立即被调用相当于python init方法
            this.name = name // 赋值属性
            this.age = age 
        }
        // 使用new的对象进行调用内部的方法
        // 创建方法// 方法名(可以设置参数){进行逻辑判断}
        sayname(){
            return this.name
        }
        sayage(){
            return this.age
        }

    }

    let p1 = new Person('aa',123)
    console.log(p1); // Person {name: 'aa', age: 123}
    // 使用创建的对象// 调用对象需要加()进行执行,和python中的class类中的方一致
    console.log(p1.sayage()); //123
    console.log(p1.sayname()); //aa 

从外部进行创建类
    // 通过外部进行对类中设置方法 Object.assign 
    // 传入两个参数1 当前的类名.prototype方法 2传入一个对象,对象中函数名(){}
    Object.assign(Person.prototype,{
        sayxx(){
            return xx
        },
        sayzz(){
            return yy
        }
    }) 

如何继承类 

        // 类的继承 使用关键字extends
        // 创建类不用加上()
        class animal {
            // es6 中的初始化方法 // 没有类对象
            constructor(name, age) {
                this.name = name //事例对象
                this.age = age // 事例对象
            }
            //创建两个对象
            show() {
                return this.name
            }
            func() {
                return this.age
            }
        }
        //继承这个animal类

        // 使用extends 继承animal 父类
        //dog 类继承animal类
        // class 关键字 子类名 extends方法 父类名
        // class dog extends animal{

        // }  

        class dog extends animal{ 
            // 子类的初始化方法,因为继承了父类的变量
            constructor(name,age,color){
                super(name,age) // 直接使用super去找父类的变量就可以
                this.color = color
            }
            // 子类的自己的方法
            saycole(){
                return `${this.name}${this.age}`
            }
            //重写父类的方法
            func() {
                return `${this.name}${this.age}`
            }
        }
        

        // 创建子类的对象
        let p1 = new dog('aa',18,'red') // p1是事例话dog 的对象
        console.log(p1); // 返回了dog的对象,内部有父类的方法和父类的事例变量

        //执行父类中的方法
        console.log(p1.show());
        //执行子类的方法
        console.log(p1.color());

16.模块化语法  

html 接受