美文网首页
Understanding ECMAScript6(上)

Understanding ECMAScript6(上)

作者: Michael_lpf | 来源:发表于2017-02-16 22:38 被阅读0次


    引言

    写下这一系列关于 ES6 笔记要从《Understanding ECMA6》 这本书说起。
    我在网上找到了 中译版,拜读了一下(对译者感激不尽!)。
    读过了书当然要整理一下知识,于是就有了这篇笔记。

    先看 Scott 老师的大宝剑🗡,简单阐述了 ES6 的实用新特性👇


    Paste_Image.png

    我们慢慢道来。。。


    Part 1: 块级绑定(块级作用域)


    const 声明
    • 使用 const 声明被认为是一个常量声明,在设置初始值后便不能被更改。
      正因如此,const 声明后必须进行初始化。
      没有初始化的结果是语法错误👇
    Paste_Image.png
    • const 会阻止对变量自身值的修改,但当使用 const 声明一个对象时,对象内部的值是可以更改的👇
    Paste_Image.png
    let 声明和“暂时性死区”
    • 基本上可以用 let 声明代替 var 声明。但要注意,let 声明不会被提升,一般要手动写在作用域的顶部,以供整个代码块使用。
    • 使用 const 和 let 声明变量时,试图在声明前访问会导致引用错误,即是是 typeof() 这样普遍被认为安全的访问👇
    Paste_Image.png

    JS 引擎面对 var 声明会将其提升至顶,而面对 const 和 let 则会将其置于“暂时性死区”,在死区内访问变量都会导致错误。上面第3、4行代码不会执行的。
    但若在块外访问变量,则只会返回一个可能和预期不一样的结果而已,不至于报错。

    Paste_Image.png
    循环内的函数
    • 以下代码并未返回我们预期的结果👇
    Paste_Image.png

    这是因为循环内对 i 的引用是共享的,意味着循环内定义的函数是对同一个变量(循环结束时的值)的引用。
    我们使用立即执行函数修复这个问题👇

    Paste_Image.png

    如今使用 let 声明循环中的变量可以达到同样的效果,更简洁👇

    Paste_Image.png

    这是因为每次循环,都创建一个变量绑定,每个函数拥有了变量的副本,于是输出不同的值。


    不添加属性到全局对象

    let 和 const 声明全局变量/常量时,并非会在全局对象上添加属性,这与 var 声明完全不同👇

    Paste_Image.png
    块级作用域最佳实践
    • 老思路是:普遍使用 let 代替 var 声明,当需要声明一个需要保护的变量时使用 const。
    • 新思路是:普遍使用 const 声明,只有当确定变量需要被更改的时候使用 let(依据是大部分变量初始化后不需要被修改,而意料外的改动是BUG源头之一)。


    Part 2: 函数


    参数默认值
    • ES6 中参数默认值的使用大致如下👇
    Paste_Image.png

    只有当参数未传递👇


    Paste_Image.png

    或是指定参数为 undefined 时👇

    Paste_Image.png

    默认参数值才会被使用。


    参数默认值对 arguments 对象的影响

    在 ES5 非严格模式下,arguments 对象会更新自己以反映参数的变化👇

    Paste_Image.png

    在 ES5 严格模式下,为打消混乱,arguments 对象不再更新👇

    Paste_Image.png

    在使用了 ES6 默认参数值的函数中,arguments 对象的表现和严格模式下的表现一致(无论是否声明了严格模式)👇

    Paste_Image.png

    (👆上面例子中第二个 console.log 输出 false,是因为调用是没有传入参数 b,此时 b 为 2,arguments[1] 为 undefined。)
    至此,我们也就可用 arguments 来了解参数的初始状态了。


    参数默认值表达式
    • 可以将前面的参数作为后面的参数的默认值👇
    function foo(first, second = first){
      return first + second
    }
    

    如此,调用时可以只传一个实参了foo(1) //2,乍看没什么生产用途。
    不急,还可以将前面的参数传递给一个函数来产生后面的参数👇

    function increase(val){
      return val + 5;
    }
    function foo(first, second = increase(first)){
      return first + second
    }
    foo(1);  //  7
    
    • 仅允许前面的参数作为后面参数的默认值,反之是行不通的。
      这是因为默认参数在函数初次调用时被初始化,为 p1 赋值为 p2 时,p2 还没有被初始化呢👇


      Paste_Image.png

    剩余参数
    • 类似 ...restArgs 这样的语法可以用来创建剩余参数👇
    Paste_Image.png
    • ES6 中的函数构造器被增强了。
      上面两个同样作为 ES6 新特性的 “剩余参数” 和 “参数默认值” 自然也在新的函数构造器中得到了支持👇
    Paste_Image.png

    一个返回第一个剩余参数的例子👇

    Paste_Image.png
    箭头函数
    • 总览:
      • 箭头函数被设计用来代替匿名函数表达式。
      • 拥有更简洁的语法。
      • 没有 arguments 对象。
      • 不能修改 this 绑定。
    • 箭头函数在语法层面有很多变体,但所有变体都以参数开头,接一个箭头 => ,而后是函数体。
      当函数只有一个参数,不需要任何语法。随后是函数体,函数体会被返回,即使没有 return 👇
    var foo = val => val;
    //  等同于
    var foo = function(val){
      return val;
    }
    

    当函数多于一个参数,需要圆括号将参数括起来👇

    var add = (a, b) => a + b;
    //  等同于
    var add = function(a, b){
      return a + b;
    }
    

    若函数没有参数,那么必须使用一对空圆括号👇

    var foo = () => true;
    //  等同于
    var foo = function(){
      return true;
    }
    

    当函数包含多个语句时,需要花括号括起来,并明确 return 👇

    var cal = (a, b) => { a++; return a + b}
    //  等同于
    var cal = function(a, b){
      a++
      return a + b;
    }
    

    如果函数内需要返回对象字面量,则需要用圆括号括起来👇

    var getObj = () => ({ name:'Nick', age:30});
    //  等同于
    var getObj = function(){
      return {
        name:'Nick',
        age:30
      }
    }
    
    • 创建立即调用函数
      传统的立即调用函数,有两种书写方法,圆括号是否包裹 “参数调用” 部分都可以👇
    //  一个立即调用函数
    var person1 = (function(name){
      return {
        getName: function(){
          return name
        }
      }
    })('Nick');
    //  另一个立即调用函数
    var person2 = (function(name){
      return {
        getName: function(){
          return name;
        }
      }
    }('Penny'));
    

    但使用箭头函数时,圆括号只需包裹函数体,不要包裹 “参数调用” 部分👇

    let person3 = ((name) => {
      return {
        getName: function(){
          return name;
        }
      }
    })('Marvin');
    
    • 没有 arguments 对象👇
    Paste_Image.png
    • 没有 this 绑定
      函数内部的 this 可以被更改,这取决于调用时的上下文。
      而箭头函数没有 this 绑定。如果箭头函数包含于一个非箭头函数内,那么 this 值就与该函数相等。否则 this 值就是 undefined。


    Part 3: 扩展的对象功能


    属性速记和方法简写
    • 当对象属性名和本地变量名时,可以简写👇
    //  ES5
    function person(name, age){
      return {
        name: name,
        age: age
      }
    }
    //  ES6 属性速记
    function person(name, age){
      return {
        name,
        age
      }
    }
    

    当只有属性名时,JS 引擎会查找周边作用域中同名的变量,若找到,改变量的值会赋给同名属性。

    • 省略冒号和 function 关键字,可以简写方法👇
    //  ES5
    var personA = {
      name: 'Noviziki',
      getName: function(){
        console.log(this.name);
      }
    }
    //  ES6简写
    var personB = {
      name: 'Ragger',
      gerName(){
        console.log(this.name);
      }
    }
    

    重复的对象字面量属性

    在 ES5 严格模式中,重复定义的对象属性是会造成语法错误的。
    在 ES6 中不再对其检查,无论是否声明严格模式。

    Paste_Image.png

    👆 同名属性后者的值会覆盖前者。


    明确的对象属性枚举顺序

    ES5 没有明确的对象属性枚举顺序,各 JS 引擎厂商未必统一。
    ES6 中对此作了定义:数字键总是在前,以升序排列;之后分别是字符串和符号键按添加顺序排列。

    Paste_Image.png
    修改对象的原型
    • ES5 中通过构造器或 Object.create() 来指定新建对象的原型。
      ES6 通过 setPrototypeOf() 方法改变指定对象的原型。
      接收两个参数:待修改原型的对象,将成为前者原型的对象👇
    Paste_Image.png Paste_Image.png

    Part 4: 解构:方便的数据访问


    对象解构

    在 ES5 中从对象中取值👇

    Paste_Image.png

    ES6 解构语法👇

    Paste_Image.png

    使用结构器,必须初始化,否则有语法错误👇

    Paste_Image.png

    也可以先声明,后解构赋值。
    但要将表达式写在一个圆括号中(避免被 JS 引擎解析为代码块)👇

    Paste_Image.png

    当变量没有在对象中找到同名属性的时候,无意外,它会被赋值 undefined👇

    Paste_Image.png

    当然也可以在解构中使用默认值,就像函数的参数默认值一样👇

    Paste_Image.png

    一定要将本地变量和对象属性名设置成一样的吗?这样不够灵活。当然不是👇

    Paste_Image.png

    👆不过这里的语法有些新颖,与传统对象字面量语法相反。
    被赋值的本地变量书写在冒号之后,而真正的值(此处是对象属性值)则书写在冒号之前。

    嵌套的对象结构:
    嵌套的对象结构适用于层级深一些的对象。

    Paste_Image.png
    数组解构

    与对象解构非常相似,只是不存在同名、不同名的对接方法。
    赋值的顺序由原数组顺序决定👇

    Paste_Image.png

    可以有意忽略若干项,使用 , 来占位👇

    Paste_Image.png

    同样可以有默认值👇

    Paste_Image.png

    同样可以先声明,后解构赋值。
    而且不必将表达式写在圆括号中👇

    Paste_Image.png

    嵌套的数组解构,使用 [] 下潜到数组深层👇

    Paste_Image.png

    剩余项,和函数的参数剩余项又很类似,使用 ... 接收数组解构赋值的剩余项目👇

    Paste_Image.png

    数组剩余项解构在生产中有个很常用的技巧:克隆数组。

    Paste_Image.png

    本节完
    Understanding ECMAScript6(中)
    Understanding ECMAScript6(下)

    相关文章

      网友评论

          本文标题:Understanding ECMAScript6(上)

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