ES5、ES6、ES7电子教程

ES5电子教程

中文版:http://yanhaijing.com/es5/#58
英文版:https://people-mozilla.org/~jorendorff/es5.1-final.html

ES6电子教程

中文版:http://es6.ruanyifeng.com/
英文版:http://www.ecma-international.org/ecma-262/6.0/#sec-type
ES6的浏览器兼容性问题: https://segmentfault.com/a/1190000005128101

ES7电子教程

英文版:http://www.ecma-international.org/ecma-262/7.0/index.html

名词解析

(1)链接: http://www.jb51.net/article/30719.htm

  • 变量提升
    1、查找变量的顺序是:活动对象-->全局对象,一旦找到变量就停止查找
    2、javascrip函数级作用域的影响,即函数会创建新的作用域
    3、变量提升,是把变量提升提到函数的顶部,只提升变量的声明,赋值没提升。
   //场景一
    var x = 1; //x存储在全局对象中
    console.log(x); // 1
    if (true) {
        var x = 2; //x存储在活动对象中
        console.log(x); //2
    }
    console.log(x);// 2     
   //场景一
    var v='Hello World';
    (function(){
        alert(v); 
        var v='I love you';
        alert(v);
    })(); 
  //定义的三个变量
  (function(){
      var a='One';
      var b='Two';
      var c='Three';
  })();
  //实际上是这样子的:
  (function(){
      var a,b,c;
      a='One';
      b='Two';
      c='Three';
  })();
  所以在定义js变量时候,需要把变量放在块级作用域的顶端,先定义变量,以防出现错误。
  • 函数提升
    1、函数提升:就是把函数声明提到作用域的顶部
    2、函数有两种表达方式:函数声明方式和函数表达方式
    3、只有函数声明方式才能提升
  //函数声明方式
    function myTest(){
        foo();
        function foo(){
            alert("我来自 foo");
        }
    }
    myTest(); 
 //函数表达方式
    function myTest(){
        foo();
        var foo =function foo(){
            alert("我来自 foo");
        }
    }
    myTest();
  • ** 暂时性死区**
    只要一进入当前作用域,所要使用的变量就已经存在,但是不可获取,只有等到声明变量的那一行代码出现,才可以获取和使用该变量。
  • ** let与var区别**
    //不同之处
    1、let声明的变量只在let所在的代码块内有效
    2、var有变量提升,则声明之前使用不会报错;let没有变量提升,声明前使用会报错
    3、let存在暂时性死区,只要块级作用域内存在let命令,它所声明的变量就“绑定”(binding)这个区域,不再受外部的影响
       var tmp = 123;
       if (true) {
            tmp = 'abc'; // ReferenceError 
            let tmp;
       }
   4、ES6规定,若区块中存在let和const命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡在声明前就使用这些变量,均报错。
   5、ES6规定暂时性死区和let、const语句不出现变量提升,主要是为了减少运行时错误。
   6、let不允许在相同作用域内,重复声明同一个变量
  • ** 块级作用域**
    ES5只有全局作用域和函数作用域,没有块级作用域,这带来很多不合理的场景
   1、避免由于变量提升,内层变量可能会覆盖外层变量;
   2、避免用来计数的循环变量泄露为全局变量;
   3、ES6允许块级作用域的任意嵌套, 外层作用域无法读取内层作用域的变量, 内层作用域可以定义外层作用域的同名变量;
       {{{{{let insane = 'Hello World'}}}}};
       {{{{ {let insane = 'Hello World'} console.log(insane); // 报错}}}};
       {{{{ let insane = 'Hello World'; {let insane = 'Hello World'}}}}};
   4、块级作用域可以替代立即执行的匿名函数的功能
   5、ES5(严格模式)规定,函数只能在顶层作用域和函数作用域之中声明,不能在块级作用域声明
   6、ES6允许在块级作用域之中声明函数,只在大括号情况下可行,没有大括号会报错;函数声明类似于var,存在函数提升
   注意:环境导致的行为差异太大,应该避免在块级作用域内声明函数。 若需要,也应该写成函数表达式,而不是函数声明语句
  • ** 顶层对象及其属性**
    根据不同环境,顶层对象指:
    1、浏览器:window、self对象。有实体含义,即指代浏览器的窗口对象
    2、node: global对象
  ES5中,顶层对象的属性与全局变量等价,这是javascript语言设计的最大败笔之一,原因:
  1、没法在编译时就报出变量未声明的错误,只有运行时才能知道。因为全局变量可能是顶层对象的属性创造的,而属性的创造是动态的。
  2、顶层对象到处可读,不利于模块化编程
  3、人为创造全局变量
  ES6中,对顶层对象及其属性做了以下处理:
  1、保留var和function命令,其定义的全局变量依然为顶层对象的属性
  2、let、const、import、class四种命令定义的全局变量不属于顶层对象的属性
  使用this对象获取顶层对象,但具有一定局限性:
  1、全局环境中,this会返回顶层对象。
     但是,Node模块和ES6模块中,this返回的是当前模块。
  2、函数里面的this,如果函数不是作为对象的方法运行,而是单纯作为函数运行,this会指向顶层对象。
     但是,严格模式下,这时this会返回undefined。
  3、不管是严格模式,还是普通模式,new Function('return this')(),总是会返回全局对象。
     但是,如果浏览器用了CSP(Content Security Policy,内容安全政策),那么eval、new Function这些方法都可能无法使用
   在所有情况下,都取到顶层对象的方法:
    //方法一:
    (typeof window !== 'undefined'
       ? window
       : (typeof process === 'object' &&
          typeof require === 'function' &&
          typeof global === 'object')
         ? global
         : this);
    //方法二:
    var getGlobal = function () {
      if (typeof self !== 'undefined') { return self; }
      if (typeof window !== 'undefined') { return window; }
      if (typeof global !== 'undefined') { return global; }
      throw new Error('unable to locate global object');
    };   
  • 解构(Destructuring)赋值
    从数组或对象中提取值,按照对应位置,对变量赋值
  解构赋值类型:
  1、数组形式:数据结构具有Iterator接口.
        var:  var [v1, v2, ..., vN ] = array;
        let:   let [v1, v2, ..., vN ] = array;
        const:  const [v1, v2, ..., vN ] = array;
        Set结构:  let [x, y, z] = new Set(["a", "b", "c"]);
        function* fibs() {
          var a = 0;
          var b = 1;
          while (true) {
            yield a;
            [a, b] = [b, a + b];
          }
        }
        var [first, second, third, fourth, fifth, sixth] = fibs();    
       // fibs是一个Generator函数,原生具有Iterator接口。解构赋值会依次从这个接口获取值                            
  2、对象形式:对象解构赋值与数组解构赋值的区别:
      * 数组的元素按次序排序,变量的值与位置有关;左边变量在右边的值可以不赋值
      * 对象的解构赋值,右边的以字段(变量名与变量值)形式存在,与左边变量名的顺序无关; 左边的变量与右边的变量一直,不可缺少
          var { foo, bar } = { foo: "aaa", bar: "bbb" };
          foo // "aaa"
          bar // "bbb"
          var { baz } = { foo: "aaa", bar: "bbb" };
          baz // undefined
  • 模式匹配
  “模式匹配”,只要等号两边的模式相同,左边的变量就会被赋予对应的值。
    var [a,b,c]=[1,2,3]; //模式匹配法_变量的批量赋值
    console.log(b);
    //嵌套数组解构
    let [foo,[[fa],fb],fc] = [1,[[2],3],4];
    console.log(fa)
    let [one,,three] = [1,2,"123"];
    console.log(three)
    let [start, ...d]=["999",2,"56","00"];
    console.log(start)
    let [x, y, ...z] = ['a'];
    console.log(x)
    console.log(y) 
    console.log(z)
    let [...arr] = [];
    console.log(arr) //数组
    如果解构不成功,变量的值就等于undefined
    var [fo] = [];  // fo undefined
    var [bar, fo] = [1]; // fo undefined
    // 如果右边不是数组,或者严格地说,不是可遍历的结构,那么会报错:
    let [foo] = 1;
    let [foo] = false;
    let [foo] = NaN;
    let [foo] = undefined;
    let [foo] = null;
    let [foo] = {};

ES5与ES6区别

  • 变量声明方式
  ES5:2种方式。var, function
  ES6:6种方式。var, function,let, const, import, class
  • 默认值
    ES6允许变量指定默认值。
    var [foo = true] = [];
    foo // true
    [x, y = 'b'] = ['a']; // x='a', y='b'
    [x, y = 'b'] = ['a', undefined]; // x='a', y='b'
    ES6内部使用严格相等运算符(===),判断一个位置是否有值。所以,如果一个数组成员不严格等于undefined,默认值是不会生效的
    var [x = 1] = [undefined];
    x // 1
    var [x = 1] = [null];
    x // null
  上面代码中,如果一个数组成员是null,默认值就不会生效,因为null不严格等于undefined
  惰性求值: 如果默认值是一个表达式,那么这个表达式是惰性求值的,即只有在用到的时候,才会求值
  默认值可以引用解构赋值的其他变量,但是该变量必须已经声明,否则会报错。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,311评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,339评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,671评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,252评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,253评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,031评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,340评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,973评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,466评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,937评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,039评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,701评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,254评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,259评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,485评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,497评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,786评论 2 345

推荐阅读更多精彩内容

  • let 和 const 命令 let 命令 块级作用域 const 命令 顶层对象的属性 gl...
    安小明阅读 978评论 0 0
  • let 命令 块级作用域 const 命令 顶层对象的属性 global 对象 let 命令 基本用法 ES6 新...
    嘉奇呦_nice阅读 1,623评论 0 2
  • 你可能已经听说过ECMAScript 6(简称 ES6)了。ES6 是 Javascript 的下一个版本,它有很...
    奋斗的小废鱼阅读 763评论 0 16
  • 《ECMAScript6 入门》阮一峰 读书笔记 let和constlet声明的变量仅在块级作用域内有效,var声...
    亲爱的孟良阅读 711评论 1 2
  • 不知不觉间,你已经到了而立之年。 两年前,我以一名学生的身份来到你的世界里。曾幻想过会在你这会遇到什么样的人,发生...
    小时公子阅读 505评论 13 9