**以下內容均摘自ECMAScript 6 入門——阮一峰
一、let與const
1.let用於聲明變量,let聲明的變量只在代碼塊內有效‘{}’。
var a = []; for (let i = 0; i < 10; i++) { a[i] = function () { console.log(i); }; } a[6](); // 6
for循環設置循環變量是一個父作用域,循環體內部是一個子作用域
for (let i = 0; i < 3; i++) { let i = 'abc'; console.log(i); } // abc // abc // abc
2.不存在變量提升,聲明的變量一定要在聲明后使用,否則報錯。(var聲明的變量則會輸出undefined)
3.暫時性死區,不存在變量提升所導致錯誤的另外一種說法。在區塊內聲明let變量之前,這些let變量都是不可用的。
var tmp = 123; if (true) { tmp = 'abc'; // ReferenceError let tmp; }
4.let不允許在相同區塊內,重復聲明。
5.ES6的塊級作用域,外層代碼塊不受內層代碼塊的影響。
function f1() { let n = 5; if (true) { let n = 10; } console.log(n); // 5 }
6.const聲明一個只讀的常量,修改常量的值會報錯,只聲明不賦值會報錯。
7.const只在塊級作用域內有效,存在暫時性死區,不可重復聲明。
8.const實際上保證的,是變量指向內存地址保存的數據不可改動,這點在簡單數據類型和復合數據類型的行為上會有差異,因為復合數據類型保存的是數據指針。
const a = []; a.push('Hello'); // 可執行 a.length = 0; // 可執行 a = ['Dave']; // 報錯
9.關於頂層對象,游覽器中為window,Node中為global。全局環境中,this
會返回頂層對象(嚴格模式返回undefined)。但是,Node 模塊和 ES6 模塊中,this
返回的是當前模塊。
二、變量的解構賦值
1.數組的解構賦值(在數組中提取變量進行匹配)
let [foo, [[bar], baz]] = [1, [[2], 3]]; foo // 1 bar // 2 baz // 3 let [ , , third] = ["foo", "bar", "baz"]; third // "baz" let [x, , y] = [1, 2, 3]; x // 1 y // 3 let [head, ...tail] = [1, 2, 3, 4]; head // 1 tail // [2, 3, 4] let [x, y, ...z] = ['a']; x // "a" y // undefined z // []
2.允許指定默認值(當提取成員===undefined,默認值才會生效)
let [foo = true] = []; foo // true let [x = 1] = [undefined]; x // 1 let [x = 1] = [null]; x // null
3.對象的解構賦值(變量名與屬性名同名才能取到正確的值)
let { bar, foo } = { foo: "aaa", bar: "bbb" }; foo // "aaa" bar // "bbb" let { baz } = { foo: "aaa", bar: "bbb" }; baz // undefined
4.對象的解構賦值可以用於嵌套結構對象
let obj = { p: [ 'Hello', { y: 'World' } ] }; let { p: [x, { y }] } = obj; x // "Hello" y // "World"
5.對象的解構也可以指定默認值
var {x = 3} = {}; x // 3 var {x, y = 5} = {x: 1}; x // 1 y // 5 var {x: y = 3} = {}; y // 3 var {x: y = 3} = {x: 5}; y // 5 var { message: msg = 'Something went wrong' } = {}; msg // "Something went wrong"
6.字符串的解構賦值
const [a, b, c, d, e] = 'hello'; a // "h" b // "e" c // "l" d // "l" e // "o"
7.函數參數的解構賦值
function add([x, y]){ return x + y; } add([1, 2]); // 3 //為函數參數及參數的屬性指定默認值 function move({x = 0, y = 0} = {}) { return [x, y]; } move({x: 3, y: 8}); // [3, 8] move({x: 3}); // [3, 0] move({}); // [0, 0] move(); // [0, 0] //為函數的參數指定默認值 function move({x, y} = { x: 0, y: 0 }) { return [x, y]; } move({x: 3, y: 8}); // [3, 8] move({x: 3}); // [3, undefined] move({}); // [undefined, undefined] move(); // [0, 0]
8.不建議在解構賦值內加入圓括號,容易混淆模式與表達式。
三、字符串的擴展
1.includes() startsWith() endsWith()
includes():返回布爾值,表示是否找到了參數字符串。
startsWith():返回布爾值,表示參數字符串是否在原字符串的頭部。
endsWith():返回布爾值,表示參數字符串是否在原字符串的尾部。
這三個方法都支持第二個參數,表示開始搜索的位置。
2.repeat()
返回一個新字符串,表示將原字符串重復n次。參數如果是小數,會被取整。參數是負數或者Infinity
,會報錯。NaN等同於0.
3.padStart() padEnd()
padStart():頭部補全 padEnd():尾部補全
'x'.padStart(5, 'ab') // 'ababx' 'x'.padStart(4, 'ab') // 'abax' 'x'.padEnd(5, 'ab') // 'xabab' 'x'.padEnd(4, 'ab') // 'xaba' 'xxx'.padStart(2, 'ab') // 'xxx' 'xxx'.padEnd(2, 'ab') // 'xxx' 'abc'.padStart(10, '0123456789') // '0123456abc' //如果省略第二個參數,默認使用空格補全長度。 'x'.padStart(4) // ' x' 'x'.padEnd(4) // 'x '
4.模板字符串
ES6引入模板字符串(template string)是增強版的字符串,用反引號(`)標識。它可以當作普通字符串使用,也可以用來定義多行字符串,或者在字符串中嵌入變量、表達式甚至函數。
$('#result').append(` There are <b>${basket.count}</b> items in your basket, <em>${basket.onSale}</em> are on sale! `); function fn() { return "Hello World"; } `foo ${fn()} bar` // foo Hello World bar //模板字符串甚至還能嵌套 const tmpl = addrs => ` <table> ${addrs.map(addr => ` <tr><td>${addr.first}</td></tr> <tr><td>${addr.last}</td></tr> `).join('')} </table> `;
5.標簽模板
模板字符串的功能,不僅僅是上面這些。它可以緊跟在一個函數名后面,該函數將被調用來處理這個模板字符串。這被稱為“標簽模板”功能(tagged template)。
alert`123` // 等同於 alert(123)
如果模板字符里面有變量,就不是簡單的調用了,而是會將模板字符串先處理成多個參數,再調用函數。
let a = 5; let b = 10; tag`Hello ${ a + b } world ${ a * b }`; // 等同於 tag(['Hello ', ' world ', ''], 15, 50);
******“標簽模板”的一個重要應用,就是過濾 HTML 字符串,防止用戶輸入惡意內容。
6.String.raw()
String.raw
方法,往往用來充當模板字符串的處理函數,返回一個斜杠都被轉義(即斜杠前面再加一個斜杠)的字符串,對應於替換變量后的模板字符串。
String.raw`Hi\n${2+3}!`; // 返回 "Hi\\n5!" String.raw`Hi\u000A!`; // 返回 "Hi\\u000A!"
四、正則的拓展
1.字符串對象共有 4 個方法,可以使用正則表達式:match()
、replace()
、search()
和split()
。全都定義在RegExp
對象上。
2.ES6 對正則表達式添加了u
修飾符,含義為“Unicode 模式”。
//\uD83D\uDC2A是一個四個字節的 UTF-16 編碼,代表一個字符。 /^\uD83D/u.test('\uD83D\uDC2A') // false /^\uD83D/.test('\uD83D\uDC2A') // true
//正則實例對象新增unicode屬性,表示是否設置了u修飾符。 const r1 = /hello/; const r2 = /hello/u; r1.unicode // false r2.unicode // true
3.y
修飾符的作用與g
修飾符類似,也是全局匹配,后一次匹配都從上一次匹配成功的下一個位置開始。
var s = 'aaa_aa_a'; var r1 = /a+/g; var r2 = /a+/y; r1.exec(s) // ["aaa"] r2.exec(s) // ["aaa"] r1.exec(s) // ["aa"] r2.exec(s) // null
//ES6 的正則實例對象多了sticky屬性,表示是否設置了y修飾符。 var r = /hello\d/y; r.sticky // true
4.flags
屬性,會返回正則表達式的修飾符。
// ES5 的 source 屬性 // 返回正則表達式的正文 /abc/ig.source // "abc" // ES6 的 flags 屬性 // 返回正則表達式的修飾符 /abc/ig.flags // 'gi'
五、數值的拓展
1.ES6 提供了二進制和八進制數值的新的寫法,分別用前綴0b
(或0B
)和0o
(或0O
)表示。
2.Number.isFinite(),Number.isNaN()
Number.isFinite()
用來檢查一個數值是否為有限的(finite),即不是Infinity
。如果參數類型不是數值,Number.isFinite
一律返回false
。
Number.isNaN()
用來檢查一個值是否為NaN
。如果參數類型不是NaN
,Number.isNaN
一律返回false
。
3.Number.parseInt(),Number.parseFloat()
ES6 將全局方法parseInt()
和parseFloat()
,移植到Number
對象上面,行為完全保持不變。
4.Number.isInteger(),Number.isSafeInteger()
Number.isInteger()
用來判斷一個數值是否為整數。
ES6 引入了Number.MAX_SAFE_INTEGER
和Number.MIN_SAFE_INTEGER
這兩個常量,用來表示這個范圍的上下限。Number.isSafeInteger()
則是用來判斷一個整數是否落在這個范圍之內。
5.Math對象的擴展
Math.trunc():用於去除一個數的小數部分,返回整數部分。
Math.sign():判斷一個數到底是正數(+1)、負數(-1)、零(0或-0)、還是其他值(NaN)。
Math.cbrt():用於計算一個數的立方根。
Math.clz32():返回一個數的 32 位無符號整數形式有多少個前導 0。(對於小數,Math.clz32
方法只考慮整數部分)
Math.imul():返回兩個數以 32 位帶符號整數形式相乘的結果。
Math.hypot():返回所有參數的平方和的平方根。
6.指數運算符
ES2016 新增了一個指數運算符(**
)。
2 ** 2 // 4 2 ** 3 // 8 //右結合,而不是常見的左結合。 // 相當於 2 ** (3 ** 2) 2 ** 3 ** 2 // 512