用兩個雙字節的形式表達字符時,若是直接在\u
後面跟上超過0xFFFF
的數值(好比\u20BB7
),JavaScript會理解成\u20BB+7
。因爲\u20BB
是一個不可打印字符,因此只會顯示一個空格,後面跟着一個7
。html
ES6 對這一點作出了改進,只要將碼點放入大括號,就能正確解讀該字符。es6
"\u{20BB7}" // "𠮷" "\u{41}\u{42}\u{43}" // "ABC"
JavaScript內部,字符以UTF-16的格式儲存,每一個字符固定爲2
個字節。對於那些須要4
個字節儲存的字符(Unicode碼點大於0xFFFF
的字符),JavaScript會認爲它們是兩個字符。正則表達式
var s = "𠮷"; s.length // 2 s.charAt(0) // '' s.charAt(1) // '' s.charCodeAt(0) // 55362 s.charCodeAt(1) // 57271
對於這種4
個字節的字符,JavaScript不能正確處理,字符串長度會誤判爲2
,並且charAt
方法沒法讀取整個字符,charCodeAt
方法只能分別返回前兩個字節和後兩個字節的值。數組
ES6提供了codePointAt
方法,可以正確處理4個字節儲存的字符,返回一個字符的碼點。安全
var s = '𠮷a'; s.codePointAt(0) // 134071 s.codePointAt(1) // 57271 s.codePointAt(2) // 97
codePointAt
方法的參數,是字符在字符串中的位置(從0開始)。上面代碼中,JavaScript將「𠮷a」視爲三個字符,codePointAt方法在第一個字符上,正確地識別了「𠮷」,返回了它的十進制碼點134071(即十六進制的20BB7
)。在第二個字符(即「𠮷」的後兩個字節)和第三個字符「a」上,codePointAt
方法的結果與charCodeAt
方法相同。數據結構
codePointAt
方法會正確返回32位的UTF-16字符的碼點。對於那些兩個字節儲存的常規字符,它的返回結果與charCodeAt
方法相同。app
codePointAt
方法返回的是碼點的十進制值,若是想要十六進制的值,可使用toString
方法轉換一下。函數
codePointAt
方法是測試一個字符由兩個字節仍是由四個字節組成的最簡單方法。測試
function is32Bit(c) { return c.codePointAt(0) > 0xFFFF; } is32Bit("𠮷") // true is32Bit("a") // false
ES5提供String.fromCharCode
方法,用於從碼點返回對應字符,可是這個方法不能識別32位的UTF-16字符(Unicode編號大於0xFFFF
)。this
ES6提供了String.fromCodePoint
方法,能夠識別0xFFFF
的字符
String.fromCodePoint(0x20BB7) // "𠮷" String.fromCodePoint(0x78, 0x1f680, 0x79) === 'x\uD83D\uDE80y' // true
for (let codePoint of 'foo') { console.log(codePoint) } // "f" // "o" // "o"
除了遍歷字符串,這個遍歷器最大的優勢是能夠識別大於0xFFFF
的碼點,傳統的for
循環沒法識別這樣的碼點。
var text = String.fromCodePoint(0x20BB7); for (let i = 0; i < text.length; i++) { console.log(text[i]); } // " " // " " for (let i of text) { console.log(i); } // "𠮷"
上面代碼中,字符串text
只有一個字符,可是for
循環會認爲它包含兩個字符(都不可打印),而for...of
循環會正確識別出這一個字符。
ES5對字符串對象提供charAt
方法,返回字符串給定位置的字符。該方法不能識別碼點大於0xFFFF
的字符。
ES6字符串at方法
'abc'.charAt(0) // "a" '𠮷'.charAt(0) // "\uD842" 'abc'.at(0) // "a" '𠮷'.at(0) // "𠮷"
JavaScript只有indexOf
方法,能夠用來肯定一個字符串是否包含在另外一個字符串中。ES6又提供了三種新方法。
這三個方法都支持第二個參數,表示開始搜索的位置。
var s = 'Hello world!'; s.startsWith('world', 6) // true s.endsWith('Hello', 5) // true s.includes('Hello', 6) // false
使用第二個參數n
時,endsWith
的行爲與其餘兩個方法有所不一樣。它針對前n
個字符,而其餘兩個方法針對從第n
個位置直到字符串結束。
repeat
方法返回一個新字符串,表示將原字符串重複n
次。
參數若是是小數,會被取整。
若是repeat
的參數是負數或者Infinity
,會報錯。
可是,若是參數是0到-1之間的小數,則等同於0,這是由於會先進行取整運算。0到-1之間的小數,取整之後等於-0
,repeat
視同爲0。
參數NaN
等同於0。
若是repeat
的參數是字符串,則會先轉換成數字。
'x'.repeat(3) // "xxx" 'hello'.repeat(2) // "hellohello" 'na'.repeat(0) // ""
ES7推出了字符串補全長度的功能。若是某個字符串不夠指定長度,會在頭部或尾部補全。padStart
用於頭部補全,padEnd
用於尾部補全。
'x'.padStart(5, 'ab') // 'ababx' 'x'.padStart(4, 'ab') // 'abax' 'x'.padEnd(5, 'ab') // 'xabab' 'x'.padEnd(4, 'ab') // 'xaba'
//傳統JavaScript語言 $('#result').append( 'There are <b>' + basket.count + '</b> ' + 'items in your basket, ' + '<em>' + basket.onSale + '</em> are on sale!' ); //es6引入了模板字符串 $('#result').append(` There are <b>${basket.count}</b> items in your basket, <em>${basket.onSale}</em> are on sale! `);
模板字符串(template string)是加強版的字符串,用反引號(`)標識。它能夠看成普通字符串使用,也能夠用來定義多行字符串,或者在字符串中嵌入變量。
// 普通字符串 `In JavaScript '\n' is a line-feed.` // 多行字符串 `In JavaScript this is not legal.` console.log(`string text line 1 string text line 2`); // 字符串中嵌入變量 var name = "Bob", time = "today"; `Hello ${name}, how are you ${time}?`
若是在模板字符串中須要使用反引號,則前面要用反斜槓轉義。
var greeting = `\`Yo\` World!`;
若是使用模板字符串表示多行字符串,全部的空格和縮進都會被保留在輸出之中。好比<ul>
標籤前面會有一個換行。若是你不想要這個換行,可使用trim
方法消除它。
$('#list').html(`
<ul>
<li>first</li>
<li>second</li>
</ul>
`.trim());
模板字符串中嵌入變量,須要將變量名寫在${}
之中。
function authorize(user, action) { if (!user.hasPrivilege(action)) { throw new Error( // 傳統寫法爲 // 'User ' // + user.name // + ' is not authorized to do ' // + action // + '.' `User ${user.name} is not authorized to do ${action}.`); } }
大括號內部能夠放入任意的JavaScript表達式,能夠進行運算,以及引用對象屬性。
模板字符串之中還能調用函數。
若是大括號中的值不是字符串,將按照通常的規則轉爲字符串。好比,大括號中是一個對象,將默認調用對象的toString
方法。
模板字符串甚至還能嵌套。
var x = 1; var y = 2; `${x} + ${y} = ${x + y}` // "1 + 2 = 3" `${x} + ${y * 2} = ${x + y * 2}` // "1 + 4 = 5" var obj = {x: 1, y: 2}; `${obj.x + obj.y}` // 3 //調用函數 function fn() { return "Hello World"; } `foo ${fn()} bar` // foo Hello World bar
比較複雜,用到時查閱相關例子
在ES5中,RegExp構造函數的參數有兩種狀況。
第一種狀況是,參數是字符串,這時第二個參數表示正則表達式的修飾符(flag)。
flag:
g ---表示全局模式,及模式將應用與全部字符串,而非發現的第一個匹配項的大小寫
i ---表示不區分別大小寫模式,即在肯定匹配時忽略模式與字符串的大小寫
m---表示多行模式,即在到達一行文本末尾時還會繼續查找下一行中是否存在模式匹配的項
未完待續。。。
ES6提供了二進制和八進制數值的新的寫法,分別用前綴0b
(或0B
)和0o
(或0O
)表示。
0b111110111 === 503 // true 0o767 === 503 // true
若是要將0b
和0o
前綴的字符串數值轉爲十進制,要使用Number
方法。
Number('0b111') // 7 Number('0o10') // 8
ES6在Number對象上,新提供了Number.isFinite()
和Number.isNaN()
兩個方法。
Number.isFinite()
用來檢查一個數值是否爲有限的(finite)。
Number.isFinite(15); // true Number.isFinite(0.8); // true Number.isFinite(NaN); // false Number.isFinite(Infinity); // false Number.isFinite(-Infinity); // false Number.isFinite('foo'); // false Number.isFinite('15'); // false Number.isFinite(true); // false
Number.isNaN()
用來檢查一個值是否爲NaN
。
Number.isNaN(NaN) // true Number.isNaN(15) // false Number.isNaN('15') // false Number.isNaN(true) // false Number.isNaN(9/NaN) // true Number.isNaN('true'/0) // true Number.isNaN('true'/'true') // true
它們與傳統的全局方法isFinite()
和isNaN()
的區別在於,傳統方法先調用Number()
將非數值的值轉爲數值,再進行判斷,而這兩個新方法只對數值有效,非數值一概返回false
。
isFinite(25) // true isFinite("25") // true Number.isFinite(25) // true Number.isFinite("25") // false isNaN(NaN) // true isNaN("NaN") // true Number.isNaN(NaN) // true Number.isNaN("NaN") // false
ES6將全局方法parseInt()
和parseFloat()
,移植到Number對象上面,行爲徹底保持不變。
// ES5的寫法 parseInt('12.34') // 12 parseFloat('123.45#') // 123.45 // ES6的寫法 Number.parseInt('12.34') // 12 Number.parseFloat('123.45#') // 123.45
Number.isInteger()
用來判斷一個值是否爲整數。須要注意的是,在JavaScript內部,整數和浮點數是一樣的儲存方法,因此3和3.0被視爲同一個值。
ES6在Number對象上面,新增一個極小的常量Number.EPSILON
。
Number.EPSILON // 2.220446049250313e-16 Number.EPSILON.toFixed(20) // '0.00000000000000022204'
引入一個這麼小的量的目的,在於爲浮點數計算,設置一個偏差範圍。
可是若是這個偏差可以小於Number.EPSILON
,咱們就能夠認爲獲得了正確結果。Number.EPSILON
的實質是一個能夠接受的偏差範圍。
5.551115123125783e-17 < Number.EPSILON // true
用來判斷一個整數是否落在-2^53
到2^53
之間
Math.trunc():用於去除一個數的小數部分,返回整數部分。
對於非數值,Math.trunc
內部使用Number
方法將其先轉爲數值。
對於空值和沒法截取整數的值,返回NaN。
Math.sign():判斷一個數究竟是正數、負數、仍是零。
它會返回五種值:
Math.cbrt():計算一個數的立方根
未完待續。。。
ES7新增了一個指數運算符(**
),目前Babel轉碼器已經支持。
指數運算符能夠與等號結合,造成一個新的賦值運算符(**=
)。
2 ** 2 // 4 2 ** 3 // 8 let a = 2; a **= 2; // 等同於 a = a * a; let b = 3; b **= 3; // 等同於 b = b * b * b;
用於將兩類對象轉爲真正的數組:相似數組的對象(array-like object)和可遍歷(iterable)的對象(包括ES6新增的數據結構Set和Map)。
將一組值,轉換爲數組
Array.of(3, 11, 8) // [3,11,8] Array.of(3) // [3] Array.of(3).length // 1
這個方法的主要目的,是彌補數組構造函數Array()
的不足。由於參數個數的不一樣,會致使Array()
的行爲有差別。
Array() // [] Array(3) // [, , ,] Array(3, 11, 8) // [3, 11, 8]
上面代碼中,Array
方法沒有參數、一個參數、三個參數時,返回結果都不同。只有當參數個數很多於2個時,Array()
纔會返回由參數組成的新數組。參數個數只有一個時,其實是指定數組的長度。Array.of
基本上能夠用來替代Array()
或new Array()
,而且不存在因爲參數不一樣而致使的重載。它的行爲很是統一。
Array.of
老是返回參數值組成的數組。若是沒有參數,就返回一個空數組。
數組實例的find
方法,用於找出第一個符合條件的數組成員。它的參數是一個回調函數,全部數組成員依次執行該回調函數,直到找出第一個返回值爲true
的成員,而後返回該成員。若是沒有符合條件的成員,則返回undefined
。
fill
方法使用給定值,填充一個數組。
['a', 'b', 'c'].fill(7) // [7, 7, 7] new Array(3).fill(7) // [7, 7, 7]
fill
方法用於空數組的初始化很是方便。數組中已有的元素,會被所有抹去。
fill
方法還能夠接受第二個和第三個參數,用於指定填充的起始位置和結束位置。
['a', 'b', 'c'].fill(7, 1, 2) // ['a', 7, 'c']
for (let index of ['a', 'b'].keys()) { console.log(index); } // 0 // 1 for (let elem of ['a', 'b'].values()) { console.log(elem); } // 'a' // 'b' for (let [index, elem] of ['a', 'b'].entries()) { console.log(index, elem); } // 0 "a" // 1 "b"
若是不使用for...of
循環,能夠手動調用遍歷器對象的next
方法,進行遍歷。
let letter = ['a', 'b', 'c']; let entries = letter.entries(); console.log(entries.next().value); // [0, 'a'] console.log(entries.next().value); // [1, 'b'] console.log(entries.next().value); // [2, 'c']
Array.prototype.includes
方法返回一個布爾值,表示某個數組是否包含給定的值,與字符串的includes
方法相似。
[1, 2, 3].includes(2); // true [1, 2, 3].includes(4); // false [1, 2, NaN].includes(NaN); // true
該方法的第二個參數表示搜索的起始位置,默認爲0。若是第二個參數爲負數,則表示倒數的位置,若是這時它大於數組長度(好比第二個參數爲-4,但數組長度爲3),則會重置爲從0開始。
下面代碼用來檢查當前環境是否支持該方法,若是不支持,部署一個簡易的替代版本。
const contains = (() => Array.prototype.includes ? (arr, value) => arr.includes(value) : (arr, value) => arr.some(el => el === value) )(); contains(["foo", "bar"], "baz"); // => false
數組的空位指,數組的某一個位置沒有任何值。好比,Array
構造函數返回的數組都是空位。
Array(3) // [, , ,]
注意,空位不是undefined
,一個位置的值等於undefined
,依然是有值的。空位是沒有任何值,in
運算符能夠說明這一點。
0 in [undefined, undefined, undefined] // true 0 in [, , ,] // false
因爲空位的處理規則很是不統一,因此建議避免出現空位。
set
Set 是 ES6 新增的有序列表集合,它不會包含重複項。以前咱們一般用對象(Object)或者數組(Array)來實現沒有重複項的集合。
Set 支持 add(item) 方法,用來向 Set 添加任意類型的元素,若是已經添加過則自動忽略;has(item) 方法用來檢測 Set 中是否存在指定元素;delete(item) 方法用來從 Set 中刪除指定元素;clear() 用來清空 Set;獲取 Set 集合長度用 size 屬性
var set = new Set(); set.add(window); set.has(window); // true set.size; // 1 set.add(window); set.add(1); set.size; // 2 set.delete(window); set.has(window); // false set.clear(); set.size; // 0
map
Map 是 ES6 新增的有序鍵值對集合。鍵值對的 key 和 value 均可以是任何類型的元素。經過 set(key, value) 方法爲 Map 設置新的鍵值對,若是設置的 key 已經存在則用新的 value 覆蓋,Map 在比較 key 時也不作類型轉換,跟 Set 相似;Map 的 get(key) 方法用來獲取指定 key 的值;Map 的 has(key) 、 delete(key) 、clear() 這些方法和 size 屬性,與 Set 相似
var map = new Map(); var key1 = {toString : function() { return 2}}; var key2 = 2; map.set(key1, 1); map.set(key2, 2); map.has(key1); // true map.has('2'); // false,類型不一樣 map.delete(2); map.size; // 1 map.get(key2); // undefined
迭代
能夠用 ES6 提供的新方法 for...of 來遍歷它們。
Set 和 Map 有幾個方法會返回可迭代對象(Iterator Objects),分別是 entries()、keys() 和 values()。直接遍歷 Set/Map,等同於遍歷 entries();keys() 和 values() 則分別返回 key 和 value 的集合;對於 Set,key 和 value 是同樣的。這些方法和 for...of 現階段都只有 Firefox 支持,下面的例子須要在 Firefox 下運行
var set = new Set(); set.add('this is a demo.'); set.add(window); set.add(top); for(let item of set) { console.log(item); }