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 提供了二进制和八进制数值的新写法,分别用前缀 - 0b或- 0B和- 0o或- 0O表示。(从 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_INTEGER和- Number.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 的误判。
- Map的- has()方法用来查找键名,- Set的- has()方法用来查找键值。
- 
数组的空位并不等于 undefined。undefined也是值,会占据数组的位置:[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,会访问到外部- function的- arguments)�。
- 不可以使用 - 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不等于- -0,- NaN等于自身。
- 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?.prop,obj?.[prop],func?.(...args),new C?.(...args)。可以组合使用。
