猫叔の杂记 · 手帐

读书笔记 - 《Understanding ECMAScript 6》

猫叔 JavaScript读书

《Understanding ECMAScript 6》是一本在Leanpub发售的开源电子书,较为详细的介绍了ES5的一些不足与在ES6中的改进以及新特性,计划慢慢读完这本书,在这里做一些笔记。

基础部分

更好的Unicode支持

这里有一篇阮一峰关于JS中Unicode的基础介绍。在ES5中,字符串中每一个字符由16位编码表示,即每个字符占用2个字节,这导致一些超过该16位编码范围的字符占用4个字节来表示,因此当字符串包含这些字符时,长度与位置计算会产生偏差:

var text = "𠮷a"; //𠮷字超过16位编码
// ES5
text.length; // 3
text.charCodeAt(0); // 55362
text.charCodeAt(1); // 57271
text.charCodeAt(2); // 97
text.charAt(0); // ""
"\u20BB7"; // "7", 被拆开为\u20BB与\u7,其中\u20BB不可打印
// ES6
Array.from(text).length; // 2
text.codePointAt(0); // 134071
text.codePointAt(1); // 57271
text.codePointAt(2); // 97
text.at(0); // "𠮷"
String.fromCodePoint(134071); // "𠮷"
"\u{20BB7}"; // "𠮷"

这个字符在Unicode中有两种表示方法,'\u01D1''\u004F\u030C',分别为单一与复合表示方法,虽然表示同一字符,但在ES5中并不相等,ES6中的normalize()函数用于将该类字符正规化:

// ES5
'\u01D1'==='\u004F\u030C' // false
// ES6
'\u01D1'.normalize() === '\u004F\u030C'.normalize(); // true

正则表达式的改进

新增正则对象初始化方式

// ES5
new RegExp('a', 'i'); // 只可用string初始化
// ES6
new RegExp(/a/i).flags; // 'i', 可用正则对象初始化,新增flags属性

新增u标识符用于更好的Unicode支持

var text = "𠮷";
// ES5
/^.$/.test(text); // false
// ES6
/^.$/u.test(text); // true,支持u标识符,可以正确匹配4字节的字符

新增的y标识符用于在每次匹配时都从开始位置匹配

var text = "aaa_aa_a";
// ES5
var r1 = /a+/g;
r1.exec(text); // ["aaa"]
r1.exec(text); // ["aa"]
// ES6
var r2 = /a+/y;
r2.exec(text); // ["aaa"]
r2.exec(text); // null
r2.sticky; // true

新增的字符串函数

var msg = "Hello";
msg.startsWith("He"); // true
msg.endsWith("o"); // true
msg.includes("ll"); // true
msg.repeat(3); // "HelloHelloHello"

Object.is

更加严格的值比较方法:

+0 === -0; // true
NaN === NaN; // false

Object.is(+0, -0); // false
Object.is(NaN, NaN); // true

Let声明

JS中没有块作用域,且由于变量提升(hoisted)问题,在块中声明的变量会被提升到函数顶部,即在该函数内块中声明变量可以在整个函数中被访问到:

function getValue(condition) {
    if (condition) {
        var value = "blue";
        return value;
    } else {
        return null;
    }
}

实际会被解释为:

function getValue(condition) {
    var value;
    if (condition) {
        value = "blue";
        return value;
    } else {
        return null;
    }
}

JS新增let声明方式,限制变量只能在块级范围内使用:

function getValue(condition) {
    if (condition) {
        let value = "blue"; // 只在该if条件下能被访问
        return value;
    } else {
        return null;
    }
}

由于let的特性,之前为了解决循环时因共享变量问题使用的闭包方式:

var funcs = [];
for (var i=0; i < 10; i++) {
    funcs.push((function(value) {
        return function() {
            console.log(value);
        }
    }(i)));
}
funcs.forEach(function(func) {
    func();
});

可以改为:

var funcs = [];
for (let i=0; i < 10; i++) {
    funcs.push(function() { console.log(i); });
}
funcs.forEach(function(func) {
    func();
})

好吧,表示细节好多,先读一遍阮一峰的《ECMAScript 6入门》 (:з」∠)

猫叔
程序员,关注设计与二次元