ES6学习笔记

ECMAScript6

ES5语言先天性不足。变量提升、内置对象的方法不灵活、模块化实现不完善

1.ES6简介

1.1概念

ES6泛指5.1版本后的JavaScript的下一代标准,2015年开始

1.2浏览器支持

kangax-compat-table/es6 at gh-pages · GerHobbelt/kangax-compat-table (github.com)

超过90%ES6语法特性已实现

前端工具babel,JavaScript编译器,可以将es6代码转换成es5代码,以获得浏览器支持

2.ES6新特性

2.1 let和const命令

  • var 会变量提升(含var语句会提至最开始执行)

  • let

    • 没有变量提升
    • 是一个块级作用域(只作用在一个{}内)更严谨
    • 不能重复声明
  • const

    • 没有变量提升
    • 块级作用域
    • 不能重复声明
    • 声明的是个常量,后续不能再改变,但可以修改声明对象的属性
    • 方便作为第三方框架引入, 变量不被随意修改
  • 案例1 for循环用来计数的循环遍历泄露为全局变量:

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

    打印结果:10

    原因:循环执行结束后i变成了10,由于变量提升,再次执行函数,for循环前i=10,就都返回10

    解决,使用let 这样作用域限定在for循环内

    const arr =[];
    for(let i =0;i<10;i++){
        arr[i]=function(){
            return i;
        }
    }
    console.log(arr[5]());
    

    打印结果:5

  • 案例2 使用let/const避免污染全局变量:

    let RegExp =10;
    console.log(RegExp);
    console.log(window.RegExp);
    

    打印结果:10 RegExp()

  • 建议:默认情况用const,已知变量值需要修改使用let

2.2 es6的模板字符串

  • 模板字符串:使用反引号``,插入变量时使用${变量名}

  • 使用场景:后端返回长文本等数据,使用模板字符串拼接追加更方便

  • 案例:

    <div class="box"></div>
    <script>
        const oBox = document.querySelector('.box');
        let id =1,
            name=ddd;
        let htmlStr=`<ul>
        	<li>
        		<p id=${id}>${name}</p>
        	</li>
        </ul>`;
        //oBox.innerHTML="<ul><li><p id="+id+">"+name+"</p></li></ul>"
        //利用模板字符串简化追加结构
        oBox.innerHTML=htmlStr;
        
    </script>
    

2.3 增强的函数

2.3.1 默认值
  • 带参数默认值的函数

    //es5
    function add(a,b){
        a = a||10;
        b = b||20;
        return a+b;
    }
    console.log(add());
    
    //es6
    function add1(a=10,b=20){
        return a + b;
    }
    console.log(add1());
    
    function add2(a,b=20){
        return a + b;
    }
    console.log(add2(30));
    

    打印结果

    30
    30
    50
    
  • 默认的表达式也可以是一个函数

    function add(a,b=getVal(5)){
        return a + b;
    }
    function getVal(val){
        return val + 5;
    }
    console.log(add(10));
    

    打印结果

    20
    
2.3.2 剩余参数
  • 由三个点…和一个紧跟着的具名参数指定 …keys

  • …keys 解决了arguments的问题

  • 案例

    function pick(obj, ...keys){
        //生成一个空数组
        let result = Object.create(null);
        for (let i = 0;i<keys.length;i++){
            result[keys[i]]= obj[keys[i]];
        }
        return result;
    }
    
    let book ={
        tittle:'es6',
        author:'ddd',
        year:2023
    }
    let bookData = pick(book,'year','author');
    //{'year','author'}作为剩余参数被...keys包裹,替代Arguments伪数组
    

    打印结果

    {year:2023,author:"ddd"}
    
2.3.3 扩展运算符
  • 用…实现

  • 剩余运算符:把多个独立的合并到一个数组中,一般放在函数形参上

  • 扩展运算符:将一个数组分割,并将各个项作为分离的参数传给函数

  • 案例

    const arr =[10,20,30,50,90,100,40];
    //es5 处理数组中的最大值,使用apply
    //console.log(Math.max.apply(null,arr));
    
    //es6 扩展运算符更方便 将数组分割每个参数传递给Math.max
    console.log(Math.max(...arr));
    

    打印结果

    100
    
2.3.4 箭头函数
  • 使用=>来定义 function(){}等于()=>{}

  • 案例

    //es5
    let add = function(a,b){
        return a+b;
    }
    
    //es6
    //多个参数
    let add =(a,b)=>{
        return a+b;
    }
    //一个参数,没有参数()需要保留
    let add =val=>{
        return val+5;
    }
    //可以省略{return},=>就代表返回,返回值可以不加括号,若返回一个数组或对象,需要最外层用()包裹
    let add =(val1,val2)=> val1+val2;
    
    
    //es5闭包函数
    let fn =(function(){
        return function(){
            console.log('hello es6');
        }
    })();
    
    //es6
    let fn =(()=>{
        return ()=>{
            console.log('hello es6');
        }
    })();
    
  • this指向

    • es5中this指向:取决于调用该函数的上下文对象

    • 案例

      let PageHandle = {
          id:123,
          init: function(){
              document.addEventListener('click',function(event){
                  //报错 this.doSomeThing is not a function,因为this指向为document 不再是PageHandle
                  //可以用bind改变内部this指向
               	this.doSomeThings(event.type);
              }.bind(this),false)
          },
          doSomeThings: function(type){
              console.log(`事件类型:${type},当前id:${this.id}`);
          }
      }
      

      es6解决:利用箭头函数,箭头函数没有this指向,内部this查找上层函数作用域(链)来确定(一旦使用箭头函数,当前不存在作用域)

      let PageHandle = {
          id: 123,
          init: function(){
              //箭头函数没有作用域,内部this查找作用域链-上一层 谁定义了init函数就指向谁
              document.addEventListener('click',(event)=>{
                  console.log(this);
                  this.doSomeThings(event.type);
              },false)
          },
          doSomeThings: function (type){
              console.log(`事件类型:${type},当前id:${this.id}`);
          }
      }
      
    • 注意事项:

      • 使用箭头函数,函数内部没有arguments

      • 箭头函数不能使用new关键字实例化对象

        let Person = ()=>{
            
        };
        let p = new Person();
        //报错 function函数也是一个对象,箭头函数不是对象,其实就是一个语法糖,没有constructor
        

2.4 解构赋值

  • 对赋值运算符的一种扩展

  • 针对数组和对象来进行操作

  • 优点:代码书写简洁易懂

  • 案例

    对对象进行解构

    let node ={
        type: 'id',
        name: 'ddd'
    }
    /*es5
    let type = node.type;
    let name = node.name;*/
    //es6解构赋值
    //完全解构
    let {type,name} = node;
    console.log(type,name);
    
    let obj = {
        a:{
            name:"张三"
        }b:[],
        c:'hello,world'    
    }
    //不完全解构 可忽略某些属性
    let {a} = obj;
    console.log(a)//剩余运算符
    let {a,...res}= obj;
    //默认值
    let {a,b=30}={a:20};
    

    对数组进行解构

    let arr =[1,2,3];
    let [a,b]=arr;//不完全解构
    let [a,b,c]=arr;//完全解构
    
    //对数组嵌套解构
    let [a,[b],c] = [1,[2],3];
    

2.5 扩展的对象的功能

  • es6允许直接写入变量和函数作为变量的属性和方法

    //eg1
    const name ='ddd',age=20;
    const person ={
        name,
        age,
        sayName(){
            console.log(this.name);
        }
    }
    person.sayName();
    //eg2
    function fn(x,y){
        return {x,y};
        //es5
        //return {x:x,y:y};
    }
    console.log(fn(10,20));
    
    //eg3属性的赋值器setter和取值器getter
    let cart ={
        wheel:4,
        set(newVal){
            if(newVal<this.wheel){
                throw new Error('轮子数过少,请重设')
            }
            this.wheel = newVal;
        },
        get(){
            return this.wheel;
        }
    }
    cart.set(6);
    console.log(cart.get());
    
  • 注意:简写的对象方法不能当作构造函数使用

  • es6允许用表达式作为属性名,将表达式放在方括号内

    const name='a';
    const obj = {
        isShow:true,
        [name+'bc']:123,
    	['f'+name](){
            console.log(this);
        }
    }
    
  • 对象的扩展方法

    • **is()**比较两个值是否严格相等,等价于===,区别在于更严格,

      egconsole.log(Object.is(NaN,NaN))//true

      console.log(NaN === NaN);//false

    • **assign()**对象的合并

      Object.assign(target,obj1,obj2.....)将obj1,obj2…的所有属性都合并到target对象并进行返回

      let newObj = Object.assign({},{a:1},{b:2});
      console.log(newObj);//output: {a:1,b:2}
      

2.6 Symbol

  • 一个新的原始数据类型,它表示是独一无二的值,内存地址不相同

  • 主要用途:用来定义对象的私有变量

  • 案例

    const name = Symbol('name');
    const name2 = Symbol('name');
    console.log(name === name2);//false
    
    let s1 = Symbol('s1');
    let obj ={
        [s1]:'ddd'
    };
    //obj[s1]='ddd';
    console.log(obj[s1]);//ddd
    

    注意:使用Symbol定义的对象中的变量,取值必须用**[变量名]**

  • 缺点:

    • 不易对对象的属性进行操作,比如不能用for循环取出对象中Symbol声明的属性
    • 解决:
      • let s =Object.getOwnPropertySymbols(obj);
      • let m = Reflect.ownKeys(obj);

2.7 Map和Set

2.7.1 Set
  • 又名集合,无重复值的有序列表

  • set的方法

    let set = new Set();
    
    //添加元素
    set.add(2);
    set.add('4');
    set.add([1,2,3]);
    //删除元素
    set.delete(2);
    //校验某个值是否在set中
    console.log(set.has('4'));
    //集合的长度
    console.log(set.size);
    //利用扩展运算符将set转换为数组
    let set2 = new Set([1,2,3,3,4]);
    let arr = [...set2];
    console.log(arr);
    
    
  • 注意:set中对象的引用无法被释放

    let set3 = new Set(),obj = {};
    set3.add(obj);
    //释放当前的资源 不成功
    obj = null;
    console.log(set3);
    //解决方法 WeakSet()
    let set4 = new WeakSet(),obj = {};
    set4.add(obj);
    obj = null;
    console.log(set4);
    
2.7.2 Map
  • Map类型是键值对的有序列表,键和值可以是任意类型

  • Map的方法

    let map = new Map();
    //添加键值对
    map.set('name','张三');
    map.set('age',20);
    //根据键获取值
    console.log(map.get('name'));
    //检验是否存在
    map.has('name');//true
    //删除
    map.delete('name');
    //清空
    map.clear();
    //一次性定义含多个键值对的map
    let m = new Map([
        ['a',1],
        ['c',2]
    ]);
    //和set一样不能释放引用对象,用WeakMap解决
    

2.8 数组的扩展方法

  • from()将伪数组转换为真数组

    function add(){
        //es5转换
        let arr1 =[].slice.call(arguments);
        //es6
        let arr2 =Array.from(arguments);
    }
    add(1,2,3);
    
    <ul>
        <li>1</li>
        <li>2</li>
        <li>3</li>
    </ul>
    <script>
        let lis = document.querySelectorAll('li');
        console.log(Array.from(lis));//{li,li,li}
        //通过扩展运算符 也可将伪数组转换为真正数组
        console.log([...lis]);
    </script>
    

    注意:from()还可以接收第二个参数(一个回调函数),用来对每个元素进行处理

    let liContents = Array.from(lis,ele => ele.textContent);//ele就是element的简写
    console.log(liContents);//{"1","2","3"}
    
  • of()将一组任意数据类型的值转换为数组

    console.log(Array.of(3,11,20,'30'));//{3,11,20,"30"}
    
  • copywithin()将数组中指定位置元素复制到其他位置,返回当前数组

    console.log([1,2,3,8,9,10].copyWithin(0,3));//3号位及以后的元素复制到0号位开始 并覆盖掉原数值
    //结果{8,9,10,8,9,10}
    
  • find() 查找元素findIndex()查找元素索引值

    //找出第一个符合条件的数组成员
    let num = [1,2,-10,-20,9,2].find(n => n<0);
    console.log(num);//-10
    
    //找出第一个符合条件的数组成员的索引
    let index = [1,2,-10,-20,9,2].findIndex(n => n<0);
    console.log(index);//2
    
  • entries() keys() values()返回一个遍历器 可以使用for…of循环进行

    //遍历键名
    for (let index of ['a','b'].keys()){
        console.log(index);//0 1
    }
    //遍历值
    for (let ele of ['a','b'].values()){
        console.log(ele);//a b
    }
    //遍历键值对
    for (let [index,ele] of ['a','b'].entries()){
        console.log(index,ele);//0"a" 1"b"
    }
    
  • includes()判断数组是否包换给定的值,返回一个布尔型

    console.log([1,2,3].includes(2));//true
    console.log([1,2,3].includes('4'));//false
    
    //之前 indexOf()需要判断返回值-1 1 的含义 麻烦
    console.log([1,2,3].indexOf('2'));//-1
    console.log([1,2,3].indexOf(2));//1
    

2.9 迭代器和生成器

2.9.1 迭代器(遍历器)Tterator
  • es6引入的新的遍历机制,是一个接口,作用是使各种数据结构能被快捷访问,通过Symbol.iterator生成

  • 案例

    //使用迭代
    const items = ['one','two','three'];
    //1.创建新的迭代器
    const ite = items[Symbol.iterator]();
    console.log(ite.next());//{value:"one",done:false}done表示是否遍历完成,false即还可遍历,最后一次value为undefined
    console.log(ite.next());//{value:"two",done:false}
    
  • 迭代器是一个能快捷访问数据的接口,通过Symbol.iterator创建迭代器,通过迭代器的next()获取迭代之后的结果

  • 迭代器可以看作用于遍历数据结构的指针(数据库的游标)

2.9.2 生成器Generator
  • 与迭代器紧密相关,generator是一种新的函数类型,它可以在执行过程中暂停并再次恢复

  • 通过使用关键字function*来定义一个generator函数,generator函数内部使用yield关键字可以使函数在每次调用时产生一个值,并暂停执行。这使得generator函数可以用于实现迭代器或者异步操作。

  • 与普通函数区别

    • function后 函数名前 有个*****
    • 只能在函数**内部使用yield**表达式,让函数挂起
  • 案例(普通用法)

    function* func(){
        console.log('start');
        yield 2;
        yield 3;
    }
    let fn = func();//没有输出
    console.log(fn.next());
    
    //打印结果
    start
    {value: 2, done: false}
    
  • 解释:调用generator函数不会进入函数内部,而是返回一个遍历器对象,可以调用next(),每次调用 指针指向下一个yield处 获取此前结果,随后挂起

  • 总结:generator函数分段执行,可以理解为yield语句暂停执行,next()恢复执行

  • next()传值

    function* add(){
        console.log('start');
        let x = yield '2';
        console.log('one:'+x);
        let y = yield '3';
        console.log('two:'+y);
        return x+y;
    }
    const fn = add();
    console.log(fn.next());
    console.log(fn.next());//在此处传值才会给yield'2'(x)
    //修改上一行代码
    console.log(fn.next(20));
    //第三次调用
    console.log(fn.next(30));//y被赋值为30
    
    //打印结果
    start 
    {value:"2",done: false}
    one:undefined
    {value:"3",done: false}//因为x没有被赋值
    //修改后的第二次next执行结果
    one:20
    {value:"3",done: false}
    //第三次next执行结果
    two:30
    {value:50,done:true}//value值就是return值,遇到return, done=>true
    

    x不是yield语句返回值,是next()调用,恢复当前yield执行传入的实参

  • 使用场景:为不具备Iterator接口的对象提供了遍历操作

    //生成器函数
    function* objectEntries(obj){
        //获取对象的所有key保存到数组[name,age]
        const propKeys = Object.keys(obj);
        for(const propkey of propKeys){
            yield [propkey,obj[propkey]]
        }
    }
    
    const obj = {
        name:'ddd',
        age:18
    }
    
    //用生成器给对象创建了一个遍历器
    obj[Symbol.iterator] = objectEntries;
    console.log(obj);
    
    //可以使用for of 遍历遍历器了,每次[key,value]相当于next
    for(let [key,value] of objectEntries(obj)){
        console.log(`${key}:${value}`);
    }
    
    //打印结果
    {name:"ddd",age:18,Symbol(Symbol.iterator):f}
    name:ddd
    age:18
    
  • 应用:解决异步编程,部署ajax操作,让异步代码同步化

    //回调地狱
    $.ajax({
        url:'',
        method:'get',
        success(res){
            console.log(res);
            //继续发送请求
            $.ajax({
                url:'',
                method:'get',
                success(res1){
                    //发送ajax
                    $.ajax({
                        url:'',
                        method:'get',
                        success(res2){
                            //发送ajax
                            $
                        }
                    })
                }
            })
        }
    })
    //利用生成器修改成同步
    function* main(){
        let res = yield request('');
        console.log(res);
        //发送请求完成后执行后面的操作
        console.log('数据请求完成,可以继续操作');
    }
    const ite = main();
    ite.next();
    
    function request(url){
        $.ajax({
            url,
            method:'get',
            success(res){
                ite.next(res);//传值给了res
            }
        })
    }
    
    //加载loading...页面
    //数据加载完成...(异步操作)
    //loading关闭掉
    function loadUI(){
        console.log('加载loading...页面');
    }
    function showData(){
        setTimeout(()=>{
            console.log('数据加载完毕');
        },1000);
    }
    function hideUI(){
        console.log('隐藏loading...页面');
    }
    loadUI();
    showData();
    hideUI();
    //无法控制输出 hideUI比showData晚执行
    
    //要把以上的异步改成我们需要的方式 而不是直接依次发生
    //利用生成器
    function* load(){
        loadUI();
        yield showData();
        hideUI();
    }
    //创建一个生成器
    let itLoad = load();
    //调用next(),等于执行 loadUI showData 然后挂起
    itLoad.next();
    
    function loadUI(){
        console.log('加载loading...页面');
    }
    function showData(){
        //模拟异步操作
        setTimeout(()=>{
            console.log('数据加载完毕');
            //数据加载完毕 再次调用next(),继续执行hideUI
            itLoad.next();
        },1000);
    }
    function hideUI(){
        console.log('隐藏loading...页面');
    }
    

2.10 Promise对象

2.10.1 Promise的基本使用
  • promise 承诺

  • 相当于一个容器,保存着未来才会结束的事件(异步操作)的一个结果

  • 各种异步操作都可以用同样的方法进行处理 axios内部实现通过promise

  • 特点:

    • 对象的状态不受外界影响 处理异步操作有三个状态 Pending(进行中) Resolved(成功) Rejected(失败)
    • 一旦Promise对象的状态从pending转变为fulfilled或rejected,就会触发相应的处理程序
    • 一旦状态改变就不会回退,任何时候都可以通过对象获取状态结果
    • 创建一个Promise对象时,需要传入一个执行器函数,该函数接受两个参数:resolvereject。在执行器函数中执行异步操作,并根据操作结果调用resolve或reject方法来改变Promise的状态。
  • 作用:更清晰地表达和处理异步操作,避免了回调地狱(callback hell),使得异步代码更易读、易维护

  • 使用案例:

    let pro = new Promise(function(resolved,rejected){
        //执行异步操作
        let res = {
            code: 200,
            data:{
                name:'ddd'
            }
            err:'failed'
        }
        setTimeout(()=>{
            if(res.code === 200){
                resolved(res.data);
            }else{
                rejected(res.error);
            }
        },1000);
    })
    console.log(pro);
    pro.then((val)=>{
        console.log(val);
    },(err)=>{
        console.log(err);
    });
    
    //封装 实现从外界传入timeOut时间参数
    function timeOut(ms){
        return new Promise((resolved,rejected)=>{
            setTimeOut(()=>{
                resolved('hello promise success!!')
            },ms);
        })
    }
    timeOut(2000).then((val)=>{
        console.log(val);
    })
    
    
2.10.2 使用Promise封装ajax
  • 封装异步操作 外面声明一个函数在函数中返回一个promise(因为promise函数不能传参),通过promise对异步操作进行链式调用(.then().then().catch()…)

    const getJSON = function(url){
        return new Promise((resolve,reject)=>{
            const xhr = new XMLHttpRequest();
            xhr.open('GET',url);
            xhr.onreadystatechange = handler;
            xhr.responseType = 'json';
            xhr.setRequestHeader('Accept','application/json');
            xhr.send();
            function handler(){
                //this 指向 xhr
                if(this.readyState === 4){
                    if(this.status === 200){
                        resolve(this.response);
                    }else{
                        reject(new Error(this.statusText));
                    }
                }
            }
        })
    }
    getJSON('https://leetcode.cn/studyplan/top-100-liked/')
    	.then((data)=>{
        console.log(data);//返回response
    },(error)=>{
        console.log(error);//返回错误信息
    })
    
  • then()方法,第一个参数是resolve回调函数,第二个参数是可选的,是reject状态回调函数

  • then()返回一个新的promise实例,可以采用链式编程

  • .catch(err=>{})等价于.then(null,err=>{})

    getJSON('https://leetcode.cn/studyplan/top-100-liked/')
    	.then(data=>{
        	console.log(data);//.then捕获成功
    }).catch(err=>{
        console.log(err);//.catch捕获失败
    })
    
2.10.3 promise对象的其他方法
  • resolve()将一个现有的任何对象(函数参数)转换为promise对象,随后拥有状态,可以通过.then .catch去获取

    let p =Promise.resolve('foo');
    //let p = new Promise(resolve=>resolve('foo'));
    //let p = new Promise(resolve =>{
    //    return resolve('foo');
    //})
    //以上三者等价
    p.then((data)=>{
        console.log(data);
    })
    
  • reject()也返回Promise实例,和resolve()一样

  • all()提供了并行地执行异步操作的方式。一些游戏类的素材比较多,等待图片,flash,静态资源文件都加载完毕,才进行页面的初始化

    let promise1 = new Promise((resolve,reject)=>{});
    let promise2 = new Promise((resolve,reject)=>{});
    let promise3 = new Promise((resolve,reject)=>{});
    
    let p4 = Promise.all([promise1,promise2,promise3])//p4也是一个promise实例
    
    p4.then(()=>{
        //三个都成功 才成功 并行执行异步操作
    }).catch(err=>{
        //如果有一个失败 则失败
    })
    
  • race()它接受一个可迭代对象作为参数(通常是一个包含多个 Promise 实例的数组),并返回一个新的 Promise 对象。这个新的 Promise 对象会在可迭代对象中的第一个 Promise对象状态发生改变时采用该状态值(无论是成功 (fulfilled) 还是失败 (rejected)-采用第一个失败 Promise 的拒绝原因)。

    应用在给某个异步操作设置请求超时时间,并在超时后执行相应操作。

    eg1:

    如果你有一个包含两个 Promise 实例的数组,其中一个会在 500 毫秒后成功,另一个会在 1000 毫秒后失败,那么使用 Promise.race 来处理这个数组将会返回一个新的 Promise 对象。这个新的 Promise 对象会在第一个 Promise 的状态发生改变后立即采用该状态,并将其传递给相应的处理程序。

    const promise1 = new Promise((resolve, reject) => {
      setTimeout(resolve, 500, 'one');
    });
    
    const promise2 = new Promise((resolve, reject) => {
      setTimeout(reject, 1000, 'two');
    });
    
    Promise.race([promise1, promise2])
      .then(value => {
        console.log(value); // 输出 "one"
      })
      .catch(reason => {
        // 这里不会执行
      });
    

    promise1 在 500 毫秒后已经成功,因此 Promise.race 返回的新 Promise 对象立即就会采用成功状态,并将 'one' 作为成功的值传递给 .then 处理程序。

    promise1 在 500 毫秒后已经失败reject Promise.race 返回的新 Promise 对象立即就会变为失败状态,并且采用 'one' 作为拒绝的原因,若 promise2 成功,其状态不会对新 Promise 对象产生任何影响。

    //eg2 请求图片资源
    function requestImg(imgSrc){
        return new Promise((resolve,reject)=>{
            const img = new Image();
            img.onload = function(){
                resolve(img);
            }
            img.src = imgSrc;
        });
    }
    function timeout(){
        return new Promise((resolve,reject)=>{
            setTimeout(()=>{
                reject('图片请求超时');
            },3000);
        })
    }
    Promise.race([requestImg('images/2.jpg'),timeout()]).then(data=>{
        console.log(data);//3s内成功获得图片则执行该行代码
        document.body.appendChild(data);
    }).catch(err=>{
        console.log(err);//3s内不能获取则执行此
    })
    
  • done()无论新promise对象状态成功or失败,done()都会执行

  • finally()无论新promise对象状态成功or失败,finally()都会执行

2.11 async的用法

  • async 是用于定义异步函数的关键字

  • 解决异步操作的简便方法 一个Generator的语法糖

  • 作用 使得异步操作更加方便理解和管理

  • async 关键字定义的函数将始终返回一个 Promise 对象,无论该函数是否显式地使用 return 语句,之后通过.then() .catch()对其进行调用。

  • async 函数内部可以包含 await 表达式(await后的对象会被转化为promise对象),这可以让函数在等待异步操作完成时暂停执行,并且在异步操作完成后恢复执行。函数内部有多个await .then函数会等待所有的await指令运行完的结果才执行内部回调函数

  • 在Vue中使用较多

  • 案例

    //eg1
    async function f(){
        let s = await 'hello world';
        let data = await s.split('');
        return data;
    }
    f().then(v=>{console.log(v)}).catch(e=>console.log(e));
    

    打印结果

    ["h","e","l","l","o"," ","w","o","r","l","d"]
    
    //eg2
    async function fetchData() {
      let response = await fetch('https://example.com/data');
      let data = await response.json();
      return data;
    }
    
    fetchData().then(data => {
      console.log(data);
    }).catch(error => {
      console.error(error);
    });
    
    

    定义了一个名为 fetchDataasync 函数。使用 await 关键字来等待 fetch 函数获取到数据,并且等待 Promise 的 response.json() 方法获取到 JSON 数据。由于 fetchData 函数声明为 async,它会返回一个 Promise 对象,因此我们可以使用 .then().catch() 方法来处理异步操作的结果。

2.12 类class

2.12.1 class介绍
  • class是关键字,也一种语法糖,它并没有引入新的面向对象功能,只是提供了更加直观的类定义和继承方式。
  • 使用 class 关键字可以定义一个类,类名通常采用大写首字母的驼峰命名法,并且可以通过这个类来创建(new)对象实例
  • 类中的构造函数通过 constructor 方法来定义,它用于初始化新创建的对象实例
2.12.2 造类
  • es5

    function Person(name,age){
        this.name = name;
        this.age = age;
    }
    Person.prototype.sayName = function(){
        return this.name
    }
    
  • es6

    class Person{
        constructor(name,age){
            this.name = name;
            this.age = age;
        }
        sayName(){
            return this.name
        }
        sayAge(){
            return this.age
        }
    }
    //通过Object.assign()方法一次性向类中添加多个方法
    Object.assign(Person.prototype,{
        sayName(){
            return this.name
        },
        sayAge(){
            return this.age
        }
    })
    
2.12.3 类的继承
  • 使用关键字extends

  • 使用super()子类可以继承父类的属性和方法

  • 子类可以添加自己的属性和方法

  • 案例

    class Animal{
        constructor(species){
            this.species = species;   
        }
        sayName(){
            return species;
        }
    }
    class Dog extends Animal{
        constructor(species,name,age,color){
        	super(species);//调用父类的构造函数,继承父类属性和方法
        	this.name = name;
    		this.age = age;
        	this.color = color;    
        }
        //子类添加自己的方法
        sayAge(){
            return `${this.name}${this.age}`;
        }
        //子类重写父类方法
        sayName(){
            return this.name + super.species;
        }
    }
    

2.13 模块化实现

  • 历史实现模块化:服务器commonJS 浏览器AMD

  • ES6 module是服务器和浏览器通用的模块解决方案

  • ES6模块功能主要由两个命令构成:exportimport

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

  • import导入接口用于输入其他模块提供的功能

  • 一个模块就是独立的文件,例如nodejs中一个.js文件就是一个模块

  • 在VUE REACT等框架里都常用

  • 案例

    //index.js
    export const name = 'ddd';
    export function sayName(){
        return 'ddd';
    }
    const obj = {
        foo:'foo';
    }
    export default obj;
    
    <body>
        <script type='module'>
            import obj,{name,sayName} from './modules/index.js'//obj可以是对象、类,from跟路径
            console.log(name,sayName());
           // import * as f from './modules/index.js'
           // console.log(f.default);
            //直接引入所有
        </script>
    </body>
    
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值