首页 > 代码库 > ES6学习总结

ES6学习总结

  1、ES6的产生

  JavaScript 是一个持续演进的编程语言,并由浏览器厂商、开发者和社区成员组成的委员会制定标准。委员会引入了JavaScript历史上的最大更新 ES6 (ES2016),而 ES7 是年度更新的第一版(ES2017)。

  2、ES6ES7优点

    • 简化常见编程模式

    • 使代码更容易编写以及定制底层的 JavaScript 行为。

  3、新特性

    • Class 可以让开发者更容易地编写面向对象程序,并安全地扩展extend JavaScript内建对象。

    • 箭头函数Arrow functions、默认参数default parameters和数组的遍历方法array convenience methods使得常用功能更容易编写,而不需要在项目之间复制黏贴代码。

    • JavaScript 的异步处理流和嵌套回调让人难以理解,所以 ES6 中引入了promises 、迭代器和生成器iterators, and generators以简化异步代码,让控制流更直观而不易出错。

  4、ES6基础---let命令

    • 用于声明(局部)变量,类似于var(全局),但是声明的变量只在let命令所在的代码块有效。
    • 创建块级作用域(下面详细介绍)

      1 if(true){
      2     let a=10;
      3     var b=1;
      4 }
      5 console.log(a);     //Uncaught ReferenceError: a is not defined
      6 console.log(b);        //1
    • 没有变量提升

      1 console.log(typeof str);     //undefined
      2 var str = 10;     
      3 
      4 console.log(typeof abc);     //Uncaught ReferenceError: abc is not defined
      5 let abc = 10;
    • 不允许重复声明

      1 let a=10;
      2 let a=20;
      3 console.log(a);        //Uncaught SyntaxError: Identifier ‘b‘ has already been declared
      4 
      5 var a=10;
      6 var a=20;
      7 console.log(a);        //20
    • 暂时性死区

      在块级作用域中使用let声明变量时,块级作用域会形成一个封闭的环境,不能访问外部声明的变量

      1 var c = 19;
      2 if(true) {
      3       console.log(c);
      4       let c;     //Uncaught ReferenceError: c is not defined
      5 }

 

  5、为什么需要块级作用域?

  ES5 只有全局作用域和函数作用域,没有块级作用域,这带来很多不合理的场景。

    • 第一种场景----内层变量可能会覆盖外层变量。
      1 var tmp = hi;
      2 function f() {
      3      console.log(tmp);        //这里想使用外层的tmp=‘hi‘
      4      if (false) {            //if代码块之内使用内层的tmp=‘hello‘
      5         var tmp = hello;
      6      }
      7 }
      8 f();     //但是输出结果是undefined,因为这里存在变量提升,导致内部tmp覆盖了外层的tmp
    • 第二种场景----用来计数的循环变量泄露为全局变量。
      1 var s = hello;
      2 for (let i = 0; i < s.length; i++) {
      3       console.log(s[i]);
      4 }
      5 console.log(i);     // 5  
      6 //上面代码中,变量i只用来控制循环,但是循环结束后,它并没有消失,泄露成了全局变量

  6、ES6基础---const命令

  const声明一个只读的常量

    • 旦声明,常量的值就不能改变

      1 const PI = 3.1415;        // 3.1415
      2 PI = 3;                    // TypeError: Assignment to constant variable.
    • 只声明,不赋值,也会报错

      1 const a;        // SyntaxError: Missing initializer in const declaration
    • let相同,只在声明的块级作用域中有效

      1 if (true) {
      2      const a = 5;
      3 }
      4 console.log(a);        // Uncaught ReferenceError: a is not defined
    • 不允许重复声明
      1 var message = "Hello!";
      2 let age = 25;
      3 
      4 // 以下两行都会报错
      5 const message = "Goodbye!";
      6 const age = 30;
    • 也没有变量提升,存在暂时性死区
      1 if (true) {
      2      console.log(a);     //Uncaught ReferenceError: a is not defined
      3      const a = 5;
      4 }

  7、ES6 声明变量的六种方法

    • ES5 只有两种声明变量的方法:var命令和function命令。
    • ES6除了添加letconst命令,另外两种声明变量的方法:import命令和class命令。所以,ES6 一共有6种声明变量的方法。

  8、箭头函数

    • ES6 允许使用“箭头”(=>)定义函数。
      1 var f = v => v;
    • 上面箭头函数等同于
      1 var f = function(v) {  return v;};
    • 引入箭头函数的两个作用
      • 更简短的函数书写,简化回调函数
        1 // 正常函数写法
        2 [1,2,3].map(function (x) {
        3   return x * x;
        4 });
        5 // 箭头函数写法
        6 [1,2,3].map(x => x * x);
      • 对this的词法解析,自己内部没有this
    • 使用时需注意
      • 函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。
      • 不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误。
      • 不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用 rest 参数代替。
      • 不可以使用yield命令,因此箭头函数不能用作 Generator 函数
        1 //this对象的指向是可变的,但是在箭头函数中,它是固定的。
        2 function foo() {
        3   setTimeout(() => {
        4     console.log(id:, this.id);
        5   }, 100);
        6 }
        7 var id = 21;
        8 foo.call({ id: 42 });       // id: 42
        9 //箭头函数可以让setTimeout里面的this,绑定定义时所在的作用域,而不是指向运行时所在的作用域
    • 小测试:请问下面的代码中有几个this?
       1 function foo() {
       2   return () => {
       3     return () => {
       4       return () => {
       5         console.log(id:, this.id);
       6       };
       7     };
       8   };
       9 }
      10 
      11 var f = foo.call({id: 1});
      12 
      13 var t1 = f.call({id: 2})()();     // id: 1
      14 var t2 = f().call({id: 3})();     // id: 1
      15 var t3 = f()().call({id: 4});     // id: 1

       

  上面代码之中,只有一个this,就是函数foothis,所以t1t2t3都输出同样的结果。因为所有的内层函数都是箭头函数,都没有自己的this,它们的this其实都是最外层foo函数的this

  除了this,以下三个变量在箭头函数之中也是不存在的,指向外层函数的对应变量:argumentssupernew.target

  9、promise对象

    • 异步编程的一种解决方案
      • 避免了层层嵌套的回调函数,使用链式调用方式来组织代码,更加直观
      • 提供统一的接口,使得控制异步操作更加容易。
    • 三种状态
      • Pending进行中
      • Resolved已完成(又称Fulfilled)
      • Rejected已失败
    • 基本用法
       1 //创造一个promise实例
       2 var promise = new Promise(function(resolve, reject) {
       3   // ... some code
       4 
       5   if (/* 异步操作成功 */){
       6     resolve(value);
       7   } else {
       8     reject(error);
       9   }
      10 });
      11 //实例生成后,可以用then方法分别指定Resolved状态和Reject状态的回调函数。
      12 promise.then(function(value) {
      13   // success
      14 }, function(error) {
      15   // failure
      16 });
    • promise.all()
      • 用于将多个 Promise 实例,包装成一个新的 Promise 实例。

        var p = Promise.all([p1, p2, p3]);
      • p的状态由p1p2p3决定,分成两种情况。

        (1)只有p1p2p3的状态都变成fulfilledp的状态才会变成fulfilled,此时p1p2p3的返回值组成一个数组,传递给p的回调函数。

        (2)只要p1p2p3之中有一个被`rejected`,p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数。

         1 // 生成一个Promise对象的数组
         2 var promises = [2, 3, 5, 7, 11, 13].map(function (id) {
         3   return getJSON(/post/ + id + ".json");
         4 });
         5 ?
         6 Promise.all(promises).then(function (posts) {
         7   // ...
         8 }).catch(function(reason){
         9   // ...
        10 });
        //上面代码中,promises是包含6个 Promise 实例的数组,只有这6个实例的状态都变成fulfilled,或者其中有一个变为rejected,才会调用Promise.all方法后面的回调函数

 

  先到这里吧!有什么不对的地方望大家多多指点!


ES6学习总结