ES6入门

let和const

回顾 var和function

var会把变量声明提前,但是定义没有提前;function会把声明和定义都提前;全局作用域下:使用var和function声明的变量会给window增加属性

  getA();
  console.log(a);
  var a=1;
  function getA(){
    console.log("方法执行");
  }
  输出:"方法执行"  underfined

let

区别:① 没有变量声明提升 ② 不可以重复定义 ③ 不会把该变量添加到window上面

  console.log(a);
  let a=0;
  console.log(window.a);
  let a=0;
  说明:都会报错,分别针对上面的几种情况

const

区别:也满足let的三者区别,还包含① 一旦声明必须赋值
② 一旦赋值不可以修改(但是内部的引用数据可以修改)

  const a={"a":1,"arr":[1,2,3]};
  a.arr[2]=5;
  console.log(a.arr); //[1,2,5]

作用域

es6之前只有全局作用域和私有作用域,es6添加了块级作用域

块级作用域

凡是{}都是块级作用域,在块级作用域下,var和function声明的变量依然是全局的,但是let和const声明的变量是私有的

{
  var a=0;
  let b=0;
}
console.log(a); //0
console.log(b); // b is not define

块级作用域使用

注意:{}如果想表示一个对象,不能放在行首,否则就要用()包裹或者变量接收,不然会被当成一个块级作用域

({"name":"info"});
块级作用域的:if(){}
if(){}中的函数只会提前声明不会定义,当条件成立才会定义

console.log(getA,a);  //undefined undefined
if(0){
  var a=1;
  function getA(){}
}
console.log(getA,a); //undefined undefined


console.log(getB,b);  //undefined undefined
if(1){
  console.log(getB,b); //ƒ getB(){} undefined
  var b=1;
  function getB(){}
}
console.log(getB,b); //ƒ getB(){} 1

说明:块级作用域内部的函数声明和定义被提升到块级作用域的最上部;但是块级作用域内部的变量只是声明被提升到块级作用域的最上部。

块级作用域的:for(){}
let func=[];
for(let i=0;i<10;i++){
  func.push(function(){
    console.log(i);
  })
}
func[5](); //5

var funcv=[];
for(var i=0;i<10;i++){
  funcv.push(function(){
    console.log(i);
  })
}
funcv[5](); //10

说明:对比上面两套代码得出结论,let在for(){}中使用,
每一次循环都是一个私有的作用域,互不影响;

解构赋值

数组的解构

设置默认值,如果后面是underfined则会指定默认值的相关操作,如果不是underfined(即使是null等也不行)则执行默认值操作

let a=[1,2,3,4];
let [b,c,...d]=a;
console.log(b,c,d);//1 2 [3, 4]
let [x1,x2=10]=[1,2]
console.log(x1,x2); //1,2
//省略赋值
let [,y]=[1,2];
console.log(y);//2

对象的解构赋值

数组解构赋值有顺序,对象解构赋值可以没有顺序

// let {name,age=10}={name:"qiang",age:undefined};
//{name:name}第一个name是属性值,第二个name才是变量名
//使用的都是变量名,而不是属性值
//值是undefined时候,使用默认值
let {name:name,age=10}={name:"qiang",age:undefined};
console.log(name,age); //qiang 10
//嵌套
let {list:[a,b,c]}={list:[1,2,3]};
console.log(a,b,c);//1 2 3  此时list是属性名而不是变量名,a,b,c才是变量名

其他数据类型解构赋值

//使用数组的解构赋值的形式,如果等号右边不是一个数组,默认将其转换为类数组(类似数组的对象,必须有length属性)
let [x,y]="123";
console.log(x,y);//1 2 都是字符串
//使用对象的解构赋值的形式,如果等号右边不是对象,默认转为对象
console.log(Object(1)); //Number {1}__proto__: Number[[PrimitiveValue]]: 1
let {a}=1;
console.log(a);//underfined
let {__proto__:b}=1;
console.log(b);//输出一个Number类型的对象
let {length:c}="123";//其实这个length就是 Object("123")打印之后对象的一个属性
console.log(c);//3

函数参数的赋值

function getA({name,age=10}){
    console.log(name,age);
}
function getA1({name,age=10}={}){
    console.log(name,age);
}
 getA("qiang");//undefined 10
 //这样直接调用getA函数,就相当于传递了underfined,但是underfined是没有name和age属性的
 //解决方案是如getA1={}一样赋一个空对象当作默认值
 getA();//报错


 function getA2({name="qiang",age=20}={}){
    console.log(name,age);
}
function getA3({name,age}={name:"qiang",age:20}){
    console.log(name,age);
}
getA2();//qiang 20
getA3();//qiang 20
getA2({});//qiang 20
getA3({});//undefined undefined
说明:对比这四个结果,分析区别。

字符串扩展

//1.includes  返回值布尔
//includes("指定字符",开始查找的位置(可选))
//第二个参数不是一个数字的话,就使用Number转换,例如null=>0
console.log("abs".includes('a',1));//false
//2.startswith endswith
//startswith("指定字符",开始查找的位置(可选)),参数二如果不是数字同上
console.log("anc".startsWith('a',0));//true
//endswith("指定字符",从前几个查看(可选)),参数二同上
console.log("anc".endsWith('c',2));//false
//3.repeat 重复,参数必须取整,不可以负数或者Infinity
console.log("abc".repeat(4));//abcabcabcabc
//4.padStart  padEnd  ES7
//按照指定,补全字符串的指定长度
//参数一:长度,参数二:指定字符
let str="ab";
console.log(str.padStart(5,'g'));//gggab
console.log(str.padEnd(5,'gg'));//abggg
//5.模板字符串
let a="abc";
console.log(`${a}测试`);//abc测试

数组的扩展

Array类上的扩展

//1.Array  是一个函数,返回一个数组
console.log(Array("abc"));//["abc"]
console.log(Array(1,2,3));//[1,2,3]
//如果只有一个参数,且是数字,返回有N个空位的数组
console.log(Array[7]);//[empty*7] 得到七个空位
//Array.of和Array等效,除了在只有一个数字参数时候返回的还是数组
console.log(Array.of(7));//[7]
//Array.from(数组/类数组(有length属性)) 返回一个数组
console.log(Array.from("abc"));//["a","b","c"]

数组原型上的扩展

//1.copyWith 从原数组中读取内容,替换数组的指定位置的内容,修改的是原数组
//(替换目标的起始位置target,查找的起始位置begin,查找的结束位置end(不包括))
let arr=[1,2,3,4,5,6,7,8];
// console.log(arr.copyWithin(4,2,4))// [1, 2, 3, 4, 3, 4, 7, 8]
// console.log(arr)// [1, 2, 3, 4, 3, 4, 7, 8]
//参数三:省略,会直接查找到最后,如果有超出部分,自动截取,原数组length不变
console.log(arr.copyWithin(4,5)) //[1, 2, 3, 4, 6, 7, 8, 8]
//2.fill 按照指定字符填充数组,修改原数组
console.log(arr.fill("呵呵"));// ["呵呵", "呵呵", "呵呵", "呵呵", "呵呵", "呵呵", "呵呵", "呵呵"]
console.log(arr.fill("111",3));//["呵呵", "呵呵", "呵呵", "111", "111", "111", "111", "111"]
//参数三:不包含
console.log(arr.fill("222",3,6));// ["呵呵", "呵呵", "呵呵", "222", "222", "222", "111", "111"]
//3.filter,过滤,返回一个新的数组
let arr1=[1,2,3,4,5,6];
let a1=arr1.filter((value,index,arr)=>{
    return value>4;
});
console.log(arr1);//[1,2,3,4,5,6]
console.log(a1);//[5,6]
//4.find  先遍历数组,一旦参数函数返回true,停止查找,返回当前项
//finindex 先遍历数组,一旦参数函数返回true,停止查找,返回当前项索引
let arr2=[1,2,3,4,5,6];
let a2=arr2.find(item=>{
    return item>4;
})
console.log(a2);//5
console.log(arr2.findIndex(item=>{
    return item>2;
}));//2
//5.includes 判断数组中有没有某一项
let arr3=[1,2,3];
console.log(arr3.includes(1));//true
console.log(arr3.includes(1,1));//false 参数二,是开始查找的位置
//6.reduce 迭代,回调函数参数一:上一次的值,参数二:当前值
console.log(arr3.reduce((pre,cur)=>{
    return pre+cur;
}));//6 第一次没有pre 会自动使用0
//7.reduceRight 和reduce一样,只是顺序从右边开始
//8.keys 遍历每一项的接口,可以使用for of/in中
//9.entries 遍历接口,可以遍历到索引和每一项
//10.补充
let arr=["a","b","c"];
arr.filter(function(item,index){
    console.log(this);//window
});
arr.filter(function(item,index){
    console.log(this);//arr
},arr);
arr.filter((item,index)=>{
    console.log(this);//window
});
说明:这种遍历类型的,即使使用箭头函数,也会this指向错误,所以可以通过第二种方式解决(recude和reduceRight不可行,因为这俩方法的参数二是指定默认值的)。

数组空位

数组空位:当前数组的某个索引位置没有任何值,underfined不是空位。判断空位,可以用in方法

//in 判断数组索引位置上有没有值
let arr=[,,,,];
console.log(arr.length);//4 此处是4而不是5,一个逗号代表一个空位
console.log(1 in arr);//false 1是索引
//es5中数组方法对空位的处理一般直接跳过空位 ,例如filter
//es6中方法奖空位处理为underfined
//题目:得到一个7个1的数组
console.log(Array(7).fill(1));

函数的扩展

//length指的是形参的个数,如果形参有默认值,就变成了形参没有默认值的个数
//一般参数的默认值放在最后面
function fn(x,y=4){}
console.log(fn.length)//1
//参数
function fn1(...arg){
    console.log(arg);//数组
    console.log(arguments);//类数组
}
fn1([1,2,3,4])

函数作用域问题

函数执行的时候先给形参赋值,形参也是私有变量,如果给形参的默认值也是一个变量,先看是不是自己的私有变量,不是自己的再找全局中是否有这个变量,没有就报错。
私有作用域:形参也是私有变量

let m=100,n=10;
function fn(x,y=x){
    console.log(x,y);
}
fn(1);//1 1

扩展运算符

  • 将非数组(类数组 length)变成数组
  • 将数组变成非数组
// 非数组=》数组
let str="123";
console.log([...str]); //['1','2','3']
// 数组=》非数组
let arr1=[1,2,3];
let arr2=[1,2,3];
console.log(arr1.concat(arr2)); //[1,2,3,1,2,3]
console.log([...arr1,...arr2]);//[1,2,3,1,2,3]
//求最大值
let arr3=[1,2,3,4,5];
console.log(Math.max(...arr3));//5
console.log(Math.max.apply(null,arr3)); //5

箭头函数

箭头函数都是匿名函数,通常函数当作参数情况下使用箭头函数

  • 箭头函数没有this指向,里面的this是上一级的作用域下的this,如果上一级仍然是箭头函数,继续向上找.
  • 箭头函数没有arguments
  • 箭头函数不可以用作构造函数,因为不可以用作new执行
let ojb={
   fn:function(){
       let fn=()=>{
           console.log(this);//{fn:f}
           console.log(arguments);//arguments is not defined
       };
       fn();
   }
}
ojb.fn() 

let ojb={
   fn:function(){
       let fn=function(){
           console.log(this);//windows
       };
       fn();
   }
}
ojb.fn() 

对象的扩展

对象的简洁方式

let name="qiang",age=20;
let info={name,age};
let str="hehe";
let obj={
    //fn:function(){} 
    fn(){}, //等效于上面
    //属性名是字符串,属性名使用[]里面可以写变量
    [str]:name,
    ["my"+str]:name,
    "str":name
}
console.log(obj.str,obj.hehe,obj.myhehe);//qiang  qiang qiang

Object的方法扩展

//1.Object ()将参数变成对象
console.log(Object(1));//Number {1}
console.log(Object(true));//Boolean {true}
//2.Object.is 判断两个值是否相等,除了下面两种,其他和===相同
//=== NaN跟NaN不相等 -0===0 true
console.log(Object.is(NaN,NaN))//true
console.log(Object.is(-0,0))//false

//3.Object.assign(obj1,obj2) 合并对象 把obj1合并到obj2上,返回obj1
let obj1={name:"qiang"};  
let obj2={age:12};  
let obj=Object.assign(obj1,obj2);
console.log(obj); //{name: "qiang", age: 12}
console.log(obj1);//{name: "qiang", age: 12}
//ES7提供了对象的扩展运算符... 如果属性重复,只保留一份
let a1={name:"hehe"};
let a2={info:"ascaa"};
let a={...a1,...a2};
console.log(a); //{name: "hehe", info: "ascaa"}

//4. Obejct.getOwnPropertyDescriptor 获取一个对象某个属性的描述
console.log(Object.getOwnPropertyDescriptor("123","length"));//{value: 3, writable: false, enumerable: false, configurable: false}

对象的get和set

let obj={
    _name:"AA",
    get name(){
        // console.log("获取");
        return this._name;
    },
    set name(val){
        // console.log("设置");
        // console.log(this==obj);//true
        this._name=val;
    }
}
console.log(obj.name); //AA
obj.name="测试";
console.log(obj.name);//测试
错误案例:
let obj={
    name:"AA",
    get name(){
        // console.log("获取");
        return this.name;
    },
    set name(val){
        // console.log("设置");
        // console.log(this==obj);//true
        this.name=val;
    }
}
obj.name="测试";
说明:这样会无限死循环,set利用是自己设置自己

Symbol

ES6新增的数据类型

//Symbol是一个新的基本数据类型,而且是一个值类型
//使用Symbol函数执行得到一个Symbol数据类型
//跟字符串差不多,但是使用symbol函数得到的数据任意一个都是独一无二完全不同的。
//symbol可以接受一个参数()是对symbol数据的一个描述
//symbol的值不可以跟其他值计算(加减乘除,凭借字符串等等,但是可以转为布尔值)
//作用:一般当作对象的属性
let sym1=Symbol();
let sym2=Symbol();
console.log(typeof sym1);//symbol
console.log(sym1===sym2);//false
let sym3=Symbol("foo");
console.log(sym3);//Symbol(foo)
// console.log(Number(sym3));//会报错
console.log(!Symbol());//false
console.log(Symbol().toString());//Symbol() 字符串

//获取
//Symbol.for() 如果之前有有相同描述的symbol找到这个值,如果么有就创建一个新的symbol
console.log(Symbol.for("foo"));//Symbol(foo)
//使用Symbol.for参数相同值就相同
let q1=Symbol.for("q");
let q2=Symbol.for("q");
console.log(q1===q2);//true,因为第一次是创建,第二次是得到,所以会相等
//Symbol.keyFor(symbol值):找到利用Symbol.for创建的值的描述
//如果使用的是Symbol创建的,利用Symbol.keyFor是得不到的,返回Underfined
console.log(Symbol.keyFor(q1)); 

Set

类似数组,只有值没有键.通过构造函数方式创建set实例,会默认去重(有size属性)

//参数是一个数组或者类数组(只要有iterable接口的数据:数组,arguments,元素集合,set,map,字符串)
console.log(new Set([1,1,2,3]));//Set(3) {1, 2, 3}
console.log(new Set(["111"]));//Set(1) {"111"}

let s=new Set([1,2,3]);
//size set实例的大小的个数
//add  增加,如果之前没有加上,有的话不加,返回增加后的set实例
//参数,一次只能加一个,不能添加多个
console.log(s.add(2)); //Set(3) {1, 2, 3}
//clear 清空
// console.log(s.clear());//underfined
//delete 删除,成功返回true,失败返回false
//has 判断有没有此项,返回布尔值
s.forEach((v1,v2,set)=>{
    console.log(v1); //v1 v2都是当前项,因为set没有key,set就是实例
});
//keys :遍历的接口 和for in/of搭配
//entries :遍历的接口 和for in/of搭配

Map

构造函数方式创建一个Map
参数是一个数组,数组每一项也是数组,有key和value
map实例的key可以是任意数据类型,这点和对象不同(对象的key必须是字符串,不是字符串会自动转成字符串)

// 一个对象,属性名必须是字符串,如果不是字符串,默认也会转成字符串
let m=new Map([[1,2],[3,4]]);
console.log(m);//Map(2) {1 => 2, 3 => 4}
//1.size
//2.get set has delete clear
//3.forEach keys values entries
let m1=new Map([[true,[{name:"name"},{age:12}]],[[1,2],"字符串"]])
console.log(m1);// {true => Array(2), Array(2) => "字符串"}

WeakMap和WeakSet

WeakSet 结构与 Set 类似,也是不重复的值的集合。但是,它与 Set 有两个区别。首先,WeakSet 的成员只能是对象,而不能是其他类型的值。
WeakSet 中的对象都是弱引用,即垃圾回收机制不考虑 WeakSet 对该对象的引用,也就是说,如果其他对象都不再引用该对象,那么垃圾回收机制会自动回收该对象所占用的内存,不考虑该对象还存在于 WeakSet 之中。
这是因为垃圾回收机制依赖引用计数,如果一个值的引用次数不为0,垃圾回收机制就不会释放这块内存。结束使用该值之后,有时会忘记取消引用,导致内存无法释放,进而可能会引发内存泄漏。WeakSet 里面的引用,都不计入垃圾回收机制,所以就不存在这个问题。因此,WeakSet 适合临时存放一组对象,以及存放跟对象绑定的信息。只要这些对象在外部消失,它在 WeakSet 里面的引用就会自动消失。
由于上面这个特点,WeakSet 的成员是不适合引用的,因为它会随时消失。另外,由于 WeakSet 内部有多少个成员,取决于垃圾回收机制有没有运行,运行前后很可能成员个数是不一样的,而垃圾回收机制何时运行是不可预测的,因此 ES6 规定 WeakSet 不可遍历。
WeakMap和WeakSet类似,只能key是对象而不是能是其他数据类型
说明:内存泄漏:例如dom在html页面上面,如果把dom节点从页面上面移除,其他地方也没有引用,这时候如果使用set/map进行相关存储,则该dom节点引用还是不为0,相当于内存浪费,此时使用weakset/weakmap的方式即可避免内存泄漏。

Proxy(拦截,代理)

对目标对象默认操作的拦截/改写

//new Proxy({目标对象},{拦截的方法})
let obj={name:"qiang",age:20};
//p1代理了obj.需要通过p1去操作代理的obj
let p1=new Proxy(obj,{
    //获取就会触发
    get(target,key ,proxy){
        //target:目标对象
        //key:属性名
        //proxy:当前实例
        return target[key];
    },
    set(target,prokey,value,receiver){
        //target:目标对象,此时就是obj
        //prokey:设置的属性名
        //value:设置的属性值
        //receiver:当前实例
        target[prokey]=value;
        return true;//如果设置成功return true否则false
    },
    //in 时候触发
    has(target,proKey){
        // 可以通过arguments查看传进来的参数
        if(proKey.startsWith("_")){
            return false;
        }
        return proKey in target;//如果有返回成功return true否则false
    },
});
console.log(p1.name);//qiang


function getObj(){
    return {name:"qiang"};
}
let p2=new Proxy(getObj,{
    //拦截作为函数操作时候的行为
    apply(target,object,args){
        //函数直接执行,call/apply方式执行,都会触发
        //args :表示所有参数
        //object:给函数修改this的
        if(object){
            object.fn=target;
            object.fn(...args);
            delete object.fn;
        }else{
            target(...args);
        }
    }
})
p2();

class

  • 静态方法可以被子类继承
  • 原型上的方法不可枚举
  • class没有变量提升
// let a=new A(10); class没有变量提升的,所以class定义要在前面
class A{
    //本身的属性
    constructor(x){
        //类本身
        //this :当前实例
        this.x=x;//增加的私有属性
    }
    //普通方法,相当于写在原型上
    getA(){}
    //静态方法,相当于写在原型上
    static getB(){
        console.log("静态方法");
    }
}
let a=new A(10);//如果没参数,可以省略()
for (const item in a) {
    //只输出x,验证了,class中,原型上的方法不可枚举
    console.log(item);//x
}



class B extends A{
    constructor(x){
        //super()必须写,因为子类没有this,this继承父类,
        //super()完毕之后才有this
        super(x);//就是父类的constructor
    }
    get A(){
        super.getA();//指向父类A的原型
    }
    static getBB(){
        super.getB();//super调用父类的静态的方法
    }
}
B.getBB();//静态方法,实例是获取不到该方法的

//采用class表达式让类直接执行
let a1=new class{
    constructor(name){
        console.log(name);
    }
}("信息");

Promise

    //实例一开始的状态就是pending状态,一旦new后,立马执行函数
    //执行顺序 new Promise中的代码 ===>  当前队列中的同步代码 ===> then(异步)里面的回调函数
    let pro1 = new Promise((resolve,reject)=>{
        //resolve 参数都是函数
        //reject 该参数是函数
        //当前两个函数只能执行一个,要么成功要么失败
        //如果在new Promise中有错误,那么会直接执行then中的第二个回调函数,并且把错误信息传给函数,把下方的注释代码去掉注释,可以看到控制台的效果
        // let; //使报错代码
        resolve("success");//成功Fulfilled
        reject("error");//失败Rejected
    });
    //then方法有两个回调函数
    pro1.then((res)=>{
        //resolve 成功的回调
        console.log(res);
    },(e)=>{
        //失败的回调
        console.log(e);
    });//成功打印出了success,如果我们把resolve函数注释掉,那么就会打印e
    console.log("因为then方法是异步的,所以不会等待,跳过直接进行这里的代码,所以这里先执行");

异步加载图片




    
    Title


catch

function loadImg(url) {
        return new Promise((resolve,reject)=>{
            let img = new Image();//创建一个img实例
            img.src = url;
            img.onload = function () {//img一旦触发onload事件,就表示成功
                resolve(img);//成功的话,就拿到这个img,并且执行then方法的第一个回调函数
            };
            img.onerror = function (e) {//img一旦触发onerror事件,就表示失败
                reject(e);//失败的话,就拿到错误信息,并且执行then方法的第二个回调函数
            }
        })
    }
    //catch方法用来捕获错误信息,在then方法中不写第二个回调函数,而是用catch来捕获错误信息
    //删掉url的部分字段,在浏览器控制台来看catch到的错误信息
    loadImg("https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/" +
        "it/u=528967148,228759238&fm=27&gp=0.jpg").then((img)=>{
            box.appendChild(img)
        //catch也可以找到then方法中的错误 去掉下面两句的注释控制台查看错误
            // let a;
            // let a;
        }).catch((e)=>{
        //捕获错误的,如果new promise中有错误会被捕获,如果then中的回调函数有错误也会被捕获
        console.log(e);
    })

all

 //console.dir(Promise) 查看Promise的方法
    //Promise.all([每一项都是Promise对象,如果不是Promise对象默认转为Promise])
    //数组中每一项都必须成功状态,才会执行Promise.all的成功的回调函数
    //默认将每一个项的参数放在数组中传回给回调函数,只要一个有错误,就会走报错的回调函数(将第一个错误参数传给回调,之后的都不会再执行)
    let p1 = new Promise((resolve, reject) => {
        resolve("OK");
    });
    let p2 = new Promise((resolve, reject) => {
        // resolve("OK");
        reject("p2Error");
    });
    let p3 = new Promise((resolve, reject) => {
        resolve("OK");
    });
    let pAll = Promise.all([p1,p2,p3]);
    console.log(pAll);//发现他也是Promise对象
    pAll.then((res)=>{
        console.log(res);//如果三个对象都是resolve成功的话,那么这里打印["OK", "OK", "OK"]
    }).catch((e)=>{
        console.log(e);//将p2改为 reject("p2Error") ,那么只打印"p2Error" 因为一旦有一个错误的,那么立马执行catch
    })

race

//只要数组中有一个对象的状态最先改变,此时当前实例的状态就跟着变
    //修改计时器延迟时间先后,查看状态改变
    //状态只跟最先改变的对象改变一次
    let p1 = new Promise((resolve, reject) => {
        setTimeout(()=>{
            resolve("OK1");
        },3000);
    });
    let p2 = new Promise((resolve, reject) => {
        setTimeout(()=>{
            resolve("OK2");
        },2200);
    });
    let p3 = new Promise((resolve, reject) => {
        setTimeout(()=>{
            resolve("OK3");
        },5000);
    });
    Promise.race([p1,p2,p3]).then((res)=>{
        console.log(res);
    }).catch((e)=>{
        console.log(e);
    })

async await

 //async函数默认返回一个promise对象
    async function getA() {
        //return出的内容就是成功回调的参数
        //如果这里出现错误,就会被catch捕获到
        // throw new Error("出错了");
        return "Cyan";
    }
    getA().then((res)=>{
        console.log(res);//打印出了"Cyan"
    }).catch((e)=>{
        console.log(e);//如果getA函数抛错,那么不会打印"Cyan",而是会打印错误
    });
    //await
    let p = new Promise((resolve, reject) =>{
        resolve("Cyan");
    });
    async function getA() {
        //await后跟Promise实例,如果不是也会默认转为Promise实例
        //直接让promise实例的回调执行 返回执行时的参数
        // console.log(await p);//"Cyan"
        //await是一个语法糖 不用通过then就可以直接拿到resolve或者reject的参数
        let a = await p;
        //等await后面的异步完成之后再去执行后面的代码
        console.log(a);
    }
    getA().then((res)=>{
        console.log(res);//这里是undefined是因为没有return
    }).catch((e)=>{
        console.log(e);
    })

你可能感兴趣的:(ES6入门)