《ES6 标准入门》 学习笔记 - 基础扩展篇

原书链接:http://es6.ruanyifeng.com/

Chapter 2:let 和 const 命令

  • 使用 Object.freeze 方法冻结 const 常量:

    const foo = Object.freeze({})
    foo.prop = 123 // It doesn't work.
    
  • 在全局作用域声明的 let / const 不会被绑定到全局变量上。

Chapter 3:变量的解构赋值

  • 事实上,只要某种数据结构具有 Iterator 接口,都可以采用数组形式的解构赋值:

    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()
    
  • let {foo, bar} = {foo: 1, bar: 2}let {foo: foo, bar: bar} = {foo: 1, bar: 2} 的简写。

  • 嵌套结构对象的解构:

    var obj = {
        p: [
            'Hello',
            {
                y: 'world'
            }
        ]
    }
    var {P: [x, { y }]} = obj // 会得到 x, y 的值,但不会得到 p ,因为 p 是模式,不是变量。 
    
    let obj = {}
    let arr = []
    ({ foo: obj.prop, bar: arr[0] } = { foo: 123, bar: true }) // 加 () 是为了避免 JS 将 {} 理解为代码块,而发生语法错误。
    
  • 解构的默认值生效的条件是属性值严格等于 undefined 。(用 null 也不行。)

  • 如果解构的是嵌套对象,子对象所在的父属性不存在,那么会报错:

    var {foo: {bar}} = {baz: 'baz'}
    
  • 字符串也支持解构赋值:

    const [a, b, c, d, e] = 'hello' // h, e, l, l, o
    const { length: len } = 'hello' // 5
    
  • 数值和布尔值的解构赋值:

    let { toString: s } = 123
    s === Number.prototype.toString // true
    let { toString: s2 } = true
    s2 === Boolean.prototype.toString // true
    
  • 关于圆括号的规则:[P025 - 026]

    • 变量声明语句中,模式不能带有圆括号
    • 函数参数中,模式不能带有圆括号
    • 不能将整个模式或嵌套模式中的一层放在圆括号中
  • 遍历 Map

    for(let [key, value] of map) {
    }
    

Chapter 4:字符串的扩展

  • ES6之前,超过 \uFFFF 的 Unicode 字符,要使用 2 个双字节形式表达。ES6 中,只要将码点放入大括号就能正确解读该字符:

    \u{41}\u{42} \\ AB
    '\u{1F680}' === '\uD83D\uDE80' // true
    
  • ES6 提供了 codePointAt 处理 4 字节储存的字符,返回一个字符的码点。不过要配合 for...of 循环解决位置序号的问题。

  • String.fromCharCode() 用于从码点返回对应字符,但是不能识别 32 位的 UTF-16 字符( Unicode 编号大于 0xFFFF )�。String.fromCodePoint() 解决了这个问题。

  • ES6 提供了 at() 方法解决 charAt 无法正确返回大于 0xFFFF 的字符的问题。

  • JavaScript 将合成字符视为两个字符(比如带注音符号的字符)。使用 normalize() 方法解决这个问题,具体用法查阅手册:

    '\u01D1\.normalize() === '\u004F\u030C'.normalize()
    
  • repeat(n) 用来将指定字符串重复 n 次,n 为小数的话,会被阶段取整,n 为负数或 Infinity 会报错。

  • ES7 提供了字符串补全长度的功能。如果某个字符串未达到指定长度,会在头部或尾部补全。padStart() 作用于头部, padEnd() 于尾部。

    'x'.padEnd(5, '123')
    
  • 标签模板:本质是一个函数,字符串模板会被拆分开并当做参数传入函数中:[P040 - P041]

    function tag (stringArr, ...vaules) {
        console.log(stringArr)
        for(let i of values) {
            console.log(values)
        }
    }
    tag`Hello ${1 + 2} world ${3 + 4}`
    /*
        arg1: ['Hello ', ' world', '']
        arg2: 3
        arg3: 7
    */
    
    // 过滤 HTML 字符串
    var message = SafeHTML`<p>${sender} has sent you a message.</p>`
    function SafeHTML (templateData) {
        var s = templateData[0]
        for (var i = 1; i < arguments.length; i++) {
            var arg = String(arguments[i])
            s += arg.replace(/&/g, '&')
                        .replace(/</g, '<')
                        .replace(/>/g, '>')
            s += templateData[i]
        }
        return s
    }
    

    标签模板还可以用于 i18n 和 JSX 函数。

  • 可以通过 String.raw() 方法取得转义前的字符串。它会替换所有变量,并转义反斜线。[�P042]

Chapter 5: 正则的扩展

[P43-48]

Chapter 6: 数值的扩展

  • ES6 提供了二进制和八进制数值的新写法,分别用前缀 0b0B0o0O 表示。(从 ES5 开始,八进制数就已经不再允许使用前缀 0 直接表示了。)

  • ES6 引入了一个非常小的常量:Number.EPSILON 。它的作用是为浮点数计算设置一个误差范围:

    0.1 + 0.2 - 0.3 === 0 // false
    0.1 + 0.2 - 0.3 < Number.EPSILON // true
    
  • ES6 引入了 Number.MAX_SAFE_INTEGERNumber.MIN_SAFE_INTEGER 两个常量,用来表示整数范围的上下限。同时,可以使用 Number.isSafeInteger() 来加以判断,但是结果不一定可靠。[P051 - 052]

  • ES6 为 Math 进行了一些扩展。具体可以查看文档。[P54 - 58]

  • ES6 新增了指数运算符( ** ):

    2 ** 3 === 8
    
    let b = 3
    b **= 3 // 27
    

Chapter 7:数组的扩展

  • Array.from() 用来将类似数组的对象或可遍历的对象转换成数组:[P060 - 061]

    let arrayLike = {
        '0': 'a',
        '1': 'b',
        '2': 'c',
        length: 3
    }
    let arr = Array.from(arrayLike)
    
    function foo () {
        var args = Array.from(arguments)
    }
    

    同时,扩展运算符( ... )也可以将某些数据结构转为数组。

    function foo () {
        var args = [...arguments]
    }
    
    const doms = [...documents.querySelectorAll('div')]
    

    只有对象部署了 Symbol.iterator 接口,才可以进行转换。同时,Array.from() 也支持类似数组的对象。所谓类似数组的对象,本质特征只有一点:具有 length 属性。

  • Array.of() 用来将一组值转换为数组:

    Array.of(1, 2, 3)
    
  • copyWithin() 用来将当前数组内部指定位置的成员复制到其他位置(会覆盖原有成员),然后返回当前数组。(会修改当前数组)

    Array.prototype.copyWithin(target, start = 0, end = this.length)
    
    [1, 2, 3, 4, 5].copyWithin(0, 3) // [4, 5, 3, 4, 5]
    
  • find() 用于找出第一个符合条件的数组成员;findIndex() 返回第一个符合条件的数组成员索引。(使用方法与 filter 类似)�

  • fill() 方法用于使用指定值填充数组:

    ['a', 'b', 'c'].fill(7) // [7, 7, 7]
    
  • entries(), keys() & values():遍历键值对、键名、键值。

    for (let index of ['a', 'b'].keys())
    for (let el of ['a', 'b'].values())
    for (let [index, el] of ['a', 'b'].entries())
    
  • includes() 不会像 indexOf() 一样使用 === 而导致对 NaN 的误判。

  • Maphas() 方法用来查找键名,Sethas() 方法用来查找键值。

  • 数组的空位并不等于 undefinedundefined 也是值,会占据数组的位置:[P065 - 066]

    0 in [undefined, undefined, undefined] // true
    0 in [, ,] // false
    

    在 ES5 中,不同函数对数组空位的处理很不一样。而 ES6 统一视为 undefined

  • 数组推导:(注意控制内存消耗)[P067 - 068]

    var a1 = [1, 2, 3, 4]
    var a2 = [for (i of a1) => i * 2]
    var a3 = [for (i of a1) => if(i < 3) i]
    

Chapter 8:函数的扩展

  • 对函数指定默认值之后,函数的 length 属性会返回没有指定默认值的参数个数。

  • 利用参数默认值,可以指定某一个参数不得省略(指定其默认值为一个函数,这个函数会抛出一个异常)

  • ES6 引入了 rest 参数( ...args ),用于获取函数的多余参数。rest 参数之后不能再有其他参数。

  • 数组的扩展运算符能够正确识别 32 位 Unicode 字符。

  • 任何类似数组的对象,或者有 Iterator 接口的对象都可以使用扩展运算符,比如 Generator

    var go = function* () {
        yield 1
        yield 2
        yield 3
    }
    [...go()]
    
  • 函数的 name 属性的行为,在 ES6 中有了变化:[P079 - 080]

    var func = function () {
        console.log('hello')
    }
    console.log(func.name)
    // ES5: ""
    // ES6: "func"
    
    const bar = function baz() {}
    console.log(bar.name)
    // ES5: "baz"
    // ES6: "baz"
    (new Function).name // "anonymous"
    
  • 箭头函数:

    • 箭头函数不能用作构造函数。

    • 不可以使用 arguments 对象(如果外部是一个 function ,会访问到外部 functionarguments)�。

    • 不可以使用 yield 命令,故不能作为 Generator 函数。

    • pipeline

      const pipeline = (...funcs) => 
          val => funcs.reduce((a, b) => b(a), val)
      const plus1 = a => a + 1
      const mult2 = a => a * 2
      const addThenMult = pipeline(plus1, mult2)
      addThenMult(5)
      
    • lambda 演算

  • ES7 提出了函数绑定运算符(::),用来替代 bind() 之类的函数:[P084 - 085]

    foo::bar // 等价于
    bar.bind(foo)
    
    foo::bar(...args) // 等价于
    bar.apply(foo, args)
    

    如果双冒号左边为空,右边是一个对象的方法,则等于将该方法绑定在该对象上:

    ::obj.foo // 等价于
    obj.foo.bind(obj)
    
  • 尾调用优化和尾递归[P086 - 087]

  • ES7 提案允许函数函数的最后一个参数有尾逗号( trailing comma )。

Chapter 9:对象的扩展

/* 
    Why this happens?
    Guess: JavaScript Scope
 */

var obj = {
    data: '123',
    getData () {
        console.log(this.data)
    }
}
obj.getData() // 123

var obj2 = {
    data: '123',
    getData: () => {
        console.log(this.data)
    }
}
obj2.getData() // undefined
  • 对象中的 Generator 函数:

    var obj = {
        * m () {
            yield 'Hello World!'
        }
    }
    
  • 属性表达式与简洁表示法不能一起使用:

    var foo = 'bar'
    var bar = 'abc'
    var baz = {
        [foo]
    } // Error
    
  • bind 方法创造的函数,name 属性返回 bound 加上原函数的名字,Function 构造函数创造的函数,name 属性返回 anonymous;如果对象方法是一个 Symbol 值,则返回这个 Symbol 值的描述。

  • Object.is() 用来判断两个值是否严格相等。它与 === 的行为基本一致。有两点不同:+0 不等于 -0NaN 等于自身。

  • Object.assign() 只复制可枚举的自有属性,而且是浅拷贝。

  • Object.setPropertyOf()Object.getPropertyOf() 用来操作 __proto__

  • Object.entries() 可以用来将一个对象转为真正的 Map 结构:const map = new Map(Object.entries(obj))

  • rest 参数 / 扩展运算符( ... )用于从一个对象取值。需要注意的是,rest 参数的复制是浅复制,对于复合类型得到的是引用,而不是副本。同时,rest 参数不会复制继承自原型对象的属性。

  • Null 传导运算符 —— 用于安全访问对象内部的属性。

    const firstName = message?.body?.user?.firstName || 'default'
    

    有四种用法:obj?.propobj?.[prop]func?.(...args)new C?.(...args) 。可以组合使用。

推荐阅读更多精彩内容

  • 《ECMAScript6 入门》阮一峰 读书笔记 let和constlet声明的变量仅在块级作用域内有效,var声...
    亲爱的孟良阅读 286评论 1 2
  • 看这本书是在markdown在做的笔记,更友好的阅读方式访问: github es6.md(https://git...
    汪汪仙贝阅读 104评论 0 0
  • 三,字符串扩展 3.1 Unicode表示法 ES6 做出了改进,只要将码点放入大括号,就能正确解读该字符。有了这...
    eastbaby阅读 999评论 0 8
  • 1.函数参数的默认值 (1).基本用法 在ES6之前,不能直接为函数的参数指定默认值,只能采用变通的方法。
    赵然228阅读 260评论 0 0
  • 歌,是人们的精神粮食。曲,是一首歌的内在美,也是外在美。而歌手却是这首歌这个故事的讲述者,每个歌手有自己的讲述方式...
    鸿Hong阅读 36评论 0 0