美文网首页
ES6入门笔记

ES6入门笔记

作者: 阿尔方斯 | 来源:发表于2018-08-09 21:11 被阅读0次

    变量的解构赋值

    • 数组的解构赋值

      • ES6允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring)
        例如:
            let[a,b,c] = [1,2,3];
        
        上面代码中,可以从数组中提取值,按照对应位置,对变量赋值。
    • 对象的解构赋值

      • 对象的解构与数组的解构有一个重要的不同,数组的元素是按次序排列的,变量的值由它的位置决定,而对象的属性没有次序,变量必须与属性同名,才能取到正确的值
        let { foo, bar } = { foo: "aaa", bar: "bbb" };  
        foo // "aaa"
        bar // "bbb"
        
    • 解构的多种用途

      • 交换变量的值
        let x = 1;
        let y = 2;
        [x, y] = [y, x];
        
      • 从函数返回多个值
        function example() {
            return [1,2,3];
        }
        let [a,b,c] = example();
        //返回一个对象
        function exm() {
            return {
                foo:1,
                bar:2
            }
        }
        let {a,b} = exm();
        
      • 解构赋值可以方便的将一组参数和变量名对应起来
        //参数是一组有次序的值
        function fn([x, y, z]){ ··· };
        f([1,2,3]);
        //参数是一组无次序的值
        function fn([x, y, z]){ ··· };
        fn([z:3, y:2, x:1]);
        
      • 提取JOSN数据,结构赋值对提取JSON对象的数据,尤其有用
        let jsonData = {
            id: 11,
            status: "OK",
            data: [123,123]
        }
        //data:number 相当于重新给data命名
        let {id, status, data:number} = jsonData;
        
        
      • 函数参数的默认值
        jQuery.ajax = function (url, {
            async = true,
            beforeSend = function () {},
            cache = true,
            complete = function () {},
            crossDomain = false,
            global = true,
            // ... more config
            } = {}) {
        // ... do stuff
        //标记:这里并不是很理解
        };
        

    字符串的扩展

    • 字符串的遍历器接口
      • ES6为字符串添加了遍历接口器,可以使字符串被 for...of 遍历
      for(let codePoint of 'foo'){
          console.log(codePoint);
      }
      // "f"
      // "o"
      // "o"
      
    • at()
      • ES5对字符串对象提供 charAt 方法,返回字符串给定位置的字符,该方法不能识别码点大于 0xFFFF的字符
      • ES6提供 string.at() 方法

    函数的拓展

    • 函数的默认参数值
      • ES6允许给函数设置默认参数值,直接写在参数后面
      function log(x, y = "world") {
          console.log(x , y);
      }
      
      • 除了简洁,ES6语法还有两个好处:首先,阅读代码的人可以立刻意识到哪些参数是可以省略的,不用查看函数体或文档;其次,有利于将来的代码优化,

    尾调用优化

    • 尾调用指某个函数的最后一步调用另一个函数

      • 函数调用会在内存中形成一个‘调用记录’,又称‘调用帧’,保存调用位置和内部变量等信息。尾调用由于是函数的最后一步操作,不需要保留外层函数的调用帧,因为调用位置、内部变量等信息不会再用到了,只要直接使用内层函数逇调用帧,取代外层函数的调用帧就可以了。
    • 尾递归

      • 递归非常耗费内存,因为需要同时保存成千上百个调用帧,很容易发生‘栈溢出’错误。但对于尾递归来说,由于只存在一个调用帧,所以永远不会发生‘栈溢出’
        • 尾递归 斐波那契数列
        function Fib2(n, ac1 = 0, ac2 = 1) {
            if( n <= 1) return ac2;
            return Fib2(n-1, ac2, ac1 + ac2);
            //在返回值的时候已经算好了 此时是尾调用 
        }
        
    • 递归函数的改写

      • 把所有用到的内部变量改写成函数的参数
      • 柯里化(currying) 意思是将多参数的函数转换为单参数的形式
      • 递归本质上是一种循环操作,一旦使用递归,最好使用尾递归
    • 严格模式

      • ES6的尾调用优化只在严格模式下开启,正常模式是无效的,因为正常模式下函数内部有两个变量,可以跟踪函数的调用栈
        • - func.arguments: 返回调用时函数的参数
        • - func.caller: 返回调用当前函数的那个函数
      • 尾调用优化是函数的调用栈会改写,因此上面两个变量就会失真。严格模式禁用这两个变量,所以尾调用模式仅在严格模式下生效
    • 尾递归优化的实现

      • 尾递归优化只在严格模式下生效,正常模式下可以采用'循环'换掉'递归'
      • 蹦床函数(trampoline)可以将递归执行转为循环执行
      function trampoline(f) {
          while(f && instanceof Function) {
              f = f();
          }
          return f;
      }
      

    数组的扩展

    扩展运算符

    • 扩展运算符(spread)是三个点(...),它好比rest参数的逆运算,将一个数组转换为逗号分隔的参数序列
      • 复制数组
        • 数组是复杂数据类型,直接复制只是复制了指向底层数据的指针,而不是克隆一个新的数组,扩展运算符提供了复制数组的简写
        const a1 = [1,2];
        const a2 = [...a1]; //写法1
        const [...a2] = a1; //写法2
        
      • 数组合并
        const a1 = ['a', 'b'];
        const a2 = ['c'];
        const a3 = ['d', 'e'];
        //ES5的合并数组
        a1.concat(a2, a3);
        //ES6的合并数组
        console.log([...a1, ...a2, ...a3]);
        
        • 这两种方法都是浅拷贝
      • 字符串
        • 扩展运算符可以将字符串转为真正的数组
        [...'hello'] //['h','e','l','l','o']
        //这种写法一个重要的好处是可以正确识别 Unicode字符
        
      • Map 和 Set 结构,Generator 函数
        • 扩展运算符内部调用的是数据结构Iterator接口,只要有Iterator接口的对象,都可以使用扩展运算符
      • Array.from()
        • Array.from 用于将两类对象转为真正的数组:类似数组的对象和可遍历的对象(包括ES6新增的数据结构 Set 和 Map)
        let arrayLike = {
            '0': 'a',
            '1': 'b',
            '2': 'c',
            length: 3
        };
        //ES5的写法
        var arr1 = [].slice.call(arrayLike);
        //ES6
        let arr2 = Array.from(arrayLike); // ['a', 'b', 'c']
        
        • 实际应用中,常见的类似数组的对象是DOM操作返回的NodeList集合,以及函数内部的 arguents 对象。 Array.from都可以将他们转换为真正的数组

    Promise

    回调函数的问题

    • 回调函数本身没有问题,他的问题出现在多个回调嵌套。假设执行完某个异步函数后在执行另一个函数,出现多次后会发生多重嵌套。这种情况称为'回调地狱'(callback hell)
    • Promise就是为了解决这种问题而提出的。采用Promise连续读取多个文件
      let readFile = require('fs-readfile-promise');
      
      readFile(filea)
      .then(function(data){
          console.log(data.toString());
      })
      .then(function() {
          return readFile(fileB);
      })
      .then(function(data){
          console.log(data.toString());
      })
      .catch(err => console.log(err))
      

    Generator 函数的概念

    • Generator 函数是协程在 ES6 的实现,最大的特点是可以交出函数的执行权(即暂停执行)
      function* gen(x) {
          var y = yield x + 2;
          return y;
      }
      //它不同于不同函数,是可以暂停执行的,所以函数名之前要加星号,以示区别
      
      • 整个 Generator 函数就是一个封装的异步任务,或者说异步任务的容器。一步操作需要暂停的地方,都用yield语句注明

    Promise 对象

    • Promise 的含义
      • Promise 就是一个容器,存储着某个未来才会结束的事件(通常是一个异步操作)的结果。
      • Promise 对象有以下两个特点
        • (1) 对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态: pending(进行中)、fulfilled(已成功)和rejected(已失败)。只有异步操作的结果可以决定当前是哪一种状态,任何其他操作都无法改变这个窗台。
        • (2) 一旦状态改变,就不会在变,任何时候都可以得到这个结果。
    • 基本用法
      • ES6规定,Promise 对象是一个构造函数,用来生成Promise实例
      • Promise 构造函数接收一个函数为参数,该函数的两个参数分别是 resolvereject , reslove 函数在异步操作成功时调用,并将异步操作的结果作为参数传递出去;reject函数的作用是在一部操作失败是调用,并将异步操作报出的错误作为参数传递出去
      • Promise实例生成之后可以用then方法分别指定 resolved状态和rejected状态的回调函数
      promise.then(function(value){
          //success
      }, function(error) {
          //failure
      })
      
    • Promise.prototype.then()
      • Promise 实例具有 then 方法,then方法是定义在原型Promise.prototype上的。它的作用是作为 Promise 实例添加状态改变时的回调函数。then方法的第一个参数是resolved状态的回调函数,第二个参数(可选)是rejected状态的回调函数
      • then 方法返回的是一个新的Promise实例(此时返回的实例不是原来的Promise 实例),因此可以采用链式写法,即then方法后面再调用另一个then方法
      getJSON('/post.json').then(function(json) {
          return json.post;
      }).then(function(post){
          //...
      });
      
      • 第一个then方法指定的回调函数,返回的是另一个Promise对象。这时,第二个then方法指定的回调函数就会等待这个新的Promise对象状态发生变化。如果变为resolved就执行下一个then的第一个参数,箭头函数的写法是:
      getJSON('post/.json').then(
          post => getJSON(params); 
      ).then(
          //第一个参数是成功后的回调函数
          comments => console.log("resolved:", comments),
          //第二个参数是失败调用的回调函数
          err => console.log("rejected", err)
          //此时函数返回的是一个对象,还可以继续 then
      ).then(
          成功调用的函数 => console.log(resolved),
          失败调用的函数(可选) => console.log(rejected)
      );
      

    相关文章

      网友评论

          本文标题:ES6入门笔记

          本文链接:https://www.haomeiwen.com/subject/lsxhbftx.html