ES5_6_7-Generator函数&深度克隆

ES5_6_7

ES6_Generator函数

  • 概念

    • 1、ES6提供的解决异步编程的方案之一
    • 2、Generator函数是一个状态机,内部封装了不同状态的数据,
    • 3、用来生成遍历器对象
    • 4、可暂停函数(惰性求值), yield可暂停,next方法可启动。每次返回的是yield后的表达式结果
  • 特点:

    • 1、function 与函数名之间有一个星号(*)

    • 2、内部用yield表达式来定义不同的状态

    • 例如:
        function* generatorExample(){
          let result = yield 'hello';  // 状态值为hello
          yield 'generator'; // 状态值为generator
        }
      
    • 3、generator函数返回的是指针对象(接11章节里iterator),而不会执行函数内部逻辑

    • 4、调用next方法函数内部逻辑开始执行,遇到yield表达式停止,返回{value: yield后的表达式结果/undefined, done: false/true}

    • 5、再次调用next方法会从上一次停止时的yield处开始,直到最后

    • 6、yield语句返回结果通常为undefined, 当调用next方法时传参内容会作为启动时yield语句的返回值。

  • <script type="text/javascript">
    
        //测试
        function* generatorTest() {
          console.log('函数开始执行');
          yield 'hello';
          console.log('函数暂停后再次启动');
          let result=yield 'generator';
          console.log(result);
        }
        // 生成遍历器对象
        let Gt = generatorTest();//返回的是指针对象
        // 执行函数,遇到yield后即暂停
        console.log(Gt); // 遍历器对象
        let result = Gt.next(); // 函数执行,遇到yield暂停
        console.log(result); // {value: "hello", done: false}
        result = Gt.next(); // 函数再次启动
        console.log(result); // {value: 'generator', done: false}
        result = Gt.next('这里可以传值');//yield的语句默认返回undefined,如果不传值默认undefined
        console.log(result); // {value: undefined, done: true}表示函数内部状态已经遍历完毕
    
        // 对象的symbol.iterator属性  指向遍历器对象
        let obj={usernameL:'xuefeng',age:12};
    
        obj[Symbol.iterator]=function* myTest() {
          yield 1,
          yield 2,
          yield 3
        };
        for (let i of obj) {
          console.log(i);
        }//输出 1 2 3
    
    </script>
    

ES6_Generator函数应用

  • 第一步先开服务器 cmd中

    • F:\前端视频教程\9尚硅谷-ES5_6_7\code\ES5_6_7\code\es_server>node bin/www
  • 测试服务器是否打开

    • ES5_6_7-Generator函数&深度克隆_第1张图片
  • <script type="text/javascript">
    
        // 案例练习
        /*
        * 需求:
        * 1、发送ajax请求获取新闻内容
        * 2、新闻内容获取成功后再次发送请求,获取对应的新闻评论内容
        * 3、新闻内容获取失败则不需要再次发送请求。
        * 
        * */ 
        function getNews(url) {
          $.get(url,function (data) {
            console.log(data);
            let url= `http://localhost:3000`+data.commentsUrl;
            SX.next(url);//此处传入url会作为 yield getNews(url);中的url
            //回调函数中的next函数被调用,就说明前面一定执行成功
          })
        }
        function* sendXML() {
          let url=yield getNews('http://localhost:3000/news?id=3');
          yield getNews(url);
        }
        //获取遍历器对象
        let SX=sendXML();
        SX.next();//先调用这个next方法   此时指针下移
    
    script>
    

ES6_async函数详解及应用

  • async函数(源自ES2017)

  • 概念: 真正意义上去解决异步回调的问题,同步流程表达异步操作

  • 本质: Generator的语法糖

  • 语法:

    • async function foo(){
        await 异步操作;
        await 异步操作;
      }
      
  • 特点:

    • 1、不需要像Generator去调用next方法,遇到await等待,当前的异步操作完成就往下执行
    • 2、返回的总是Promise对象,可以用then方法进行下一步操作
    • 3、async取代Generator函数的星号*,await取代Generator的yield
    • 4、语意上更为明确,使用简单,经临床验证,暂时没有任何副作用
  • <script type="text/javascript">
      //async的基本使用
      async function foo() {
        return new Promise( resolve => {
    //      setTimeout(function () {
    //        resolve();
    //      },2000)
        setTimeout(resolve(),2000);
        })
      }
      
      async function test() {
        console.log('开始执行',new Date().toTimeString());
        await foo();
        console.log('执行完毕',new Date().toTimeString());
      }
      test();
    
      //async里await返回值
    
      async  function  asyncPrint() {
      let result=await Promise.resolve('promise');
      console.log(result);
      result=await  Promise.reject('失败了...');
      console.log(result);
      }
      asyncPrint();//报错 Uncaught (in promise) 失败了...
      script>
    
  •  <script type="text/javascript">
         // 案例练习
        /*
        * 需求:
        * 1、发送ajax请求获取新闻内容
        * 2、新闻内容获取成功后再次发送请求,获取对应的新闻评论内容
        * 3、新闻内容获取失败则不需要再次发送请求。
        * 
        * */ 
     async  function getNews(url) {
        return new Promise((resolve, reject) => {
          $.ajax({
            method: 'GET',
            url,//同名的属性可以省略不写
            success: data => resolve(data),//ES6箭头函数
            /*error: function (error) {//正常写法
              reject();
            }*/
            error: error =>resolve(false)//当出错的时候  返回false
          })
        })
      }
      
      async  function sendXML() {
        let result=await  getNews('http://localhost:3000/news?id=2')
        console.log(result);
        if(!result){alert('暂时没有评论');}//出错result为false 取反就为true
        result=await getNews('http://localhost:3000'+result.commentsUrl);
        console.log(result);
      }
      sendXML();
    script>
    

ES6_class类使用详解

  • 通过class定义类/实现类的继承

  • 在类中通过constructor定义构造方法

  • 通过new来创建类的实例

  • 通过extends来实现类的继承

  • 通过super调用父类的构造方法

  • 重写从父类中继承的一般方法

  • <script type="text/javascript">
    
      /*function Person(name.age) {
        this.age=age;
        this.name=name;
      }
      let person=new Person('xuefeng',12);*/
    
      //定义一个人物的类
      class Person{
        //类的构造方法
        constructor(name,age){
          this.name=name;
          this.age=age;
        }
        //类的一般方法
        showName(){
          console.log('子类实例也能调用我');
          console.log(this.name,this.age);
        }//这些方法都定义在原型上
      }
      let person=new Person('tianjinfeng',12);
      person.showName();
    
      class StarPerson extends Person{
        constructor(name,age,salary){
          super(name,age);//调用父类的构造方法  一定要把父类构造器的参数传过来
          this.salary=salary;
        }
        showName() {//父类的方法重写
          console.log('调用子类的方法');
          console.log(this.name,this.age,this.salary);
        }
      }
      let p1=new StarPerson('daofeng',12,12000);
      console.log(p1);
      p1.showName();//daofeng 12 12000
    script>
    

ES6_字符串,数组的扩展

  • includes(str) : 判断是否包含指定的字符串

  • startsWith(str) : 判断是否以指定字符串开头

  • endsWith(str) : 判断是否以指定字符串结尾

  • repeat(count) : 重复指定次数

  • <script type="text/javascript">
      let str='awsl';
      console.log(str.includes('a'));//true
      console.log(str.startsWith('a'));//true
      console.log(str.endsWith('l'));//true
      
      console.log(str.repeat(3));//awslawslawsl
    script>
    
  • 二进制与八进制数值表示法: 二进制用0b, 八进制用0o

  • Number.isFinite(i) : 判断是否是有限大的数

  • Number.isNaN(i) : 判断是否是NaN

  • Number.isInteger(i) : 判断是否是整数

  • Number.parseInt(str) : 将字符串转换为对应的数值

  • Math.trunc(i) : 直接去除小数部分

  • <script type="text/javascript">
      console.log(0b1010);//10
      console.log(0o75);//61
      
      console.log(Number.isFinite(Infinity));//false  Infinity为无限大的书
      console.log(Number.isNaN(NaN));//true
      console.log(Number.isInteger(123.0));//true
      console.log(Number.parseInt('a1s5d6'));//NaN
      console.log(Number.parseInt('123a'));//123
      console.log(Math.trunc(123.231));//123
    script>
    

ES6_数组方法的扩展

  • Array.from(v) : 将伪数组对象或可遍历对象转换为真数组

  • Array.of(v1, v2, v3) : 将一系列值转换成数组

  • find(function(value, index, arr){return true}) : 找出第一个满足条件返回true的元素

  • findIndex(function(value, index, arr){return true}) : 找出第一个满足条件返回true的元素下标

  • <script type="text/javascript">
      let btns=document.getElementsByTagName('button');//这得到的数组就是伪数组,伪数组没有数组的一般方法
     /* forEach(function (item,index) {
        console.log(item);
      });//报错  伪数组不能遍历*/
      Array.from(btns).forEach(function (item,index) {
        console.log(item);
      });
      
      let arr=Array.of(1,4,'awsl',false);
      console.log(arr);//(4) [1, 4, "awsl", false]
      
      let arr2=[4,5,8,1,9,3,7,6,5];
      let result=arr2.find(function (item,index) {
        return item>5;
      });
      console.log(result);//8
      let index=arr2.findIndex(function (item,index) {
        return item>5;
      });
      console.log(index);//2
    script>
    

ES6_对象方法的扩展

  • 1.Object.is(v1, v2) :判断2个数据是否完全相等 以字符串形式判断

  • 2.Object.assign(target, source1, source2…) :将源对象的属性复制到目标对象上

  • 3.直接操作 __proto__ 属性 let obj2 = {}; obj2.__proto__ = obj1;

  • <script type="text/javascript">
      console.log(0 == -0);//true
      console.log(NaN == NaN);//false  NaN与任何值都不相等
      console.log(Object.is(0,-0));//false  字符串0和字符串-0是不一样的
      console.log(Object.is(NaN,NaN));//true  以字符串的形式来判断
      
      let obj={};
      let obj1={username: 'xuefeng',age:12};
      let obj2={sex:'女'};
      Object.assign(obj,obj1,obj2);
      console.log(obj);//age: 12 sex: "女" username: "xuefeng"
      
      let obj3={};
      let obj4={money :12000};
      obj3.__proto__=obj4;
      console.log(obj3);//{}
      console.log(obj3.money);//12000
    script>
    

ES6_set,map容器详解

  • 1.Set容器 : 无序不可重复的多个value的集合体

    • Set()
    • Set(array)
    • add(value)
    • delete(value)
    • has(value)
    • clear()
    • size
  • 2.Map容器 : 无序的 key不重复的多个key-value的集合体

    • Map()
    • Map(array)
    • set(key, value)//添加
    • get(key)
    • delete(key)
    • has(key)
    • clear()
    • size
  • <script type="text/javascript">
      let set=new Set(['a','w','s','l']);
      console.log(set.size,set);//4 Set(4) {"a", "w", "s", "l"}
      set.add(2);
      console.log(set.size,set);//5 Set(5) {"a", "w", "s", "l", 2}
      console.log(set.has('a'));//true
      
      let map=new Map([ ['daofeng',12],['xuefeng',12],['tianjinfeng',12]]);
      console.log(map);//Map(3) {"daofeng" => 12, "xuefeng" => 12, "tianjinfeng" => 12}
      map.set(10,'dian');
    script>
    

ES6_for of用法详解

  • for(let value of target){}循环遍历

    1. 遍历数组
    2. 遍历Set
    3. 遍历Map
    4. 遍历字符串
    5. 遍历伪数组
    
  • <script type="text/javascript">
      let arr=[1,4,7,5,4,8];
      let arr1=arr;
      arr=[];
      let set=new Set(arr1);//Set方法可以用来去重
      for(let i of set){
        arr.push(i);//向arr里添加元素
      }
      console.log(arr);//Array(5)
    
    script>
    

ES6_深度克隆

  • 1、数据类型:

    • 数据分为基本的数据类型(String, Number, boolean, Null, Undefined)和对象数据类型
      • 基本数据类型:
        特点: 存储的是该对象的实际数据
      • 对象数据类型:
        特点: 存储的是该对象在栈中引用,真实的数据存放在堆内存里
  • 2.复制数据

    • 基本数据类型存放的就是实际的数据,可直接复制
      • let number2 = 2;
        let number1 = number2;
    • 克隆数据:对象/数组
      • 1、区别: 浅拷贝/深度拷贝
        判断: 拷贝是否产生了新的数据还是拷贝的是数据的引用
        知识点:对象数据存放的是对象在栈内存的引用,直接复制的是对象的引用
        let obj = {username: ‘kobe’}
        let obj1 = obj; // obj1 复制了obj在栈内存的引用
      • 2、常用的拷贝技术
        1). arr.concat(): 数组浅拷贝
        2). arr.slice(): 数组浅拷贝
        3). JSON.parse(JSON.stringify(arr/obj)): 数组或对象深拷贝, 但不能处理函数数据
        4). 浅拷贝包含函数数据的对象/数组
        5). 深拷贝包含函数数据的对象/数组
  • <script type="text/javascript">
      /*
      //不会影响原数据
      let str='abcd';
      let str2=str;
      console.log(str2);//abcd
      str2='';
      console.log(str);
    
      let bool1=true;
      let bool2=bool1;
      bool2=false;
      console.log(bool1);//true
    
      //会改变原数据
      let obj={username:'xuefeng',age:12};
      let obj1=obj;
      console.log(obj1);
      obj1.username='daofeng';
      console.log(obj.username);//daofeng
    
      //拷贝数组/对象 没有生成新的数据而是复制了一份引用
      let arr=[1,4,{username:'jifeng',age:12}];
      let arr2=arr;
      arr2[0]='awsl';
      console.log(arr,arr2);//Array(3) [ "awsl", 4, {…} ]  Array(3) [ "awsl", 4, {…} ]
    
      */
      /*
      拷贝数据:
        基本数据类型
          拷贝后生成一份新的数据,修改拷贝以后的数据不会影响原数据
        对象/数组
          拷贝后不会生成新的数据,而拷贝是引用, 修改拷贝后的数据会影响原来的数据
       拷贝数据的方法
        1.直接赋值给一个变量  //浅拷贝
        2.Object.assign()  //浅拷贝
        3.Array.prototype.concat() //浅拷贝
        4.Array.prototype.slice()  //浅拷贝
        5.JSON.parse(JSON.stringify())  //深拷贝(深度拷贝),拷的数据里不能有函数
      浅拷贝(对象/数组):
        特点: 拷贝的引用,修改拷贝以后的数据也会影响原数据
      深拷贝(对象/数组):
        特点:拷贝的时候生成新数据,修改拷贝以后的数据不会影响原数据
       */
      let newObj={username:'dian'};
      let newObj2=Object.assign(newObj);
      console.log(newObj2);//{username: "dian"}
      newObj.username='feng';
      console.log(newObj);//{username: "feng"}
      console.log(newObj2);//{username: "feng"}
    
      let arr=[1,3,{username:'xiang'}];
      let arr2=arr.concat();//修改arr2的数据影响了原数据 所以是浅拷贝
      console.log(arr2);//Array(3) [ 1, 3, { username: "lei"} ]
      arr2[2].username='lei';
      console.log(arr);//Array(3) [ 1, 3, { username: "lei"} ]
      let arr3=arr.slice();//两个参数startIndex endIndex   修改了arr3的数据也影响了原数据 所以是浅拷贝
      arr3[2].username='shijinfeng';
      console.log(arr);//Array(3) [ 1, 3, { username: "shijinfeng"} ]
      console.log('*********');
    
      let arr4=JSON.parse(JSON.stringify(arr));//arr4改变没有修改原数据  所以是深拷贝
      console.log(arr4);//Array(3) [ 1, 3, { username: "yingfeng"} ]
      arr4[2].username='yingfeng';
      console.log(arr);//Array(3) [ 1, 3, { username: "shijinfeng"} ]
    script>
    
  • 深度克隆的方法(此方法还有误,需要调试)

    • <script type="text/javascript">
      /**
         * 如何实现深度拷贝(克隆)
         * 拷贝的数据里有对象/数组
         * 拷贝的数据里不能有对象/数组,
         *    即使有对象/数组可以继续遍历对象、数组拿到里面每一项值,一直拿到是基本数据类型,然后再去复制,就是深度拷贝
         */
        //知识储备
        /*
        如何判断数据类型  arr ---> Array  null==>Null
        1.typeof返回的数据类型:String Number Boolean Undefined Object Function
        2.Object.prototype.toString.call(obj)
        3.
         */
        let result='abcd';
        console.log(Object.prototype.toString.call(result));//[object String]
        console.log(Object.prototype.toString.call(result).slice(8,-1));//String
      
        //for in循环  对象(的属性名)  数组(的下标)
        let obj={username:'xuefeng',age:12};
        for (let i in obj){
          console.log(i);
        }
        let arr =[1,3,'awsl'];
        for (let i in arr){
          console.log(i);
        }
      
        //定义检测数据类型的功能函数
        function checkedType(target) {
          return Object.prototype.toString.call(target);
        }
        //实现深度克隆 --> 对象/数组
        function clone(target) {
          //判断拷贝的数据类型
          //初始化变量result 成为最终克隆的数据
          let result,targetType =checkedType(target);
          if(targetType === 'Object'){
            result ={};
          }else if(targetType === 'Array'){
            result=[];
          }else{
            return target;// 如果是其他数据类型不复制,直接将数据返回
          }
      
          //遍历目标数据
          for(let i in target){
            //获取遍历数据结构的每一项值
            let value=target[i];
            //判断目标结构里的每一项值是否存在对象/数组
            if(checkedType(value) === 'Object'||checkedType(value) ==='Array'){
              //继续遍历获取到的value值
              result[i]=clone(value);
            }else{//获取到的value值是基本的数据类型或者是函数
              result[i]=value;
            }
          }
          return result;
        }
      
      
        let arr3=[1,2,{username:'xuefeng',age:12}];
        let arr4=clone(arr3);
        console.log(arr4);//Array(3) [ 1, 2, { username: "xuefeng", age: 12} ]
        arr4[2].username='lian';
        console.log(arr3,arr4);
      
        let obj3={username:'tianjinfeng',age:12};
        let obj4=clone(obj3);
        console.log(obj4);//{username: "tianjinfeng", age: 12}
        obj4.username='shijinfeng';
        console.log(obj3,obj4);
      script>
      

ES7_方法介绍

  • 1.指数运算符(幂): **

  • 2.Array.prototype.includes(value) : 判断数组中是否包含指定value

  • <script type="text/javascript">
      console.log(3 ** 3);//27
      
      let arr=[1,4,7,59,11,'abv'];
      console.log(arr.includes('a'));//false  这里判断是否对等 不是模糊匹配
      
    script>
    

你可能感兴趣的:(前端,ES5_6_7)