ECMAScript 6 筆記(二)

ES6中的基本擴展

1、字符串的擴展

  1. 字符的Unicode表示法

  用兩個雙字節的形式表達字符時,若是直接在\u後面跟上超過0xFFFF的數值(好比\u20BB7),JavaScript會理解成\u20BB+7。因爲\u20BB是一個不可打印字符,因此只會顯示一個空格,後面跟着一個7html

  ES6 對這一點作出了改進,只要將碼點放入大括號,就能正確解讀該字符。es6

"\u{20BB7}"
// "𠮷"

"\u{41}\u{42}\u{43}"
// "ABC"

  2. codePointAt()

  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

 

  3. String.fromCodePoint()

  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

 

  4. 字符串的遍歷器接口

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循環會正確識別出這一個字符。

  5. at()

  ES5對字符串對象提供charAt方法,返回字符串給定位置的字符。該方法不能識別碼點大於0xFFFF的字符。

  ES6字符串at方法

'abc'.charAt(0) // "a"
'𠮷'.charAt(0) // "\uD842"

'abc'.at(0) // "a"
'𠮷'.at(0) // "𠮷"

   6. normalize()

  7. includes(), startsWith(), endsWith() 

  JavaScript只有indexOf方法,能夠用來肯定一個字符串是否包含在另外一個字符串中。ES6又提供了三種新方法。

  • includes():返回布爾值,表示是否找到了參數字符串。
  • startsWith():返回布爾值,表示參數字符串是否在源字符串的頭部。
  • endsWith():返回布爾值,表示參數字符串是否在源字符串的尾部。

  這三個方法都支持第二個參數,表示開始搜索的位置。

var s = 'Hello world!';

s.startsWith('world', 6) // true
s.endsWith('Hello', 5) // true
s.includes('Hello', 6) // false

 

  使用第二個參數n時,endsWith的行爲與其餘兩個方法有所不一樣。它針對前n個字符,而其餘兩個方法針對從第n個位置直到字符串結束。

  8. repeat()

  repeat方法返回一個新字符串,表示將原字符串重複n次。

  參數若是是小數,會被取整。

  若是repeat的參數是負數或者Infinity,會報錯。

  可是,若是參數是0到-1之間的小數,則等同於0,這是由於會先進行取整運算。0到-1之間的小數,取整之後等於-0repeat視同爲0。

  參數NaN等同於0。

  若是repeat的參數是字符串,則會先轉換成數字。

'x'.repeat(3) // "xxx"
'hello'.repeat(2) // "hellohello"
'na'.repeat(0) // ""

 

  9. padStart(),padEnd()

   ES7推出了字符串補全長度的功能。若是某個字符串不夠指定長度,會在頭部或尾部補全。padStart用於頭部補全,padEnd用於尾部補全。

'x'.padStart(5, 'ab') // 'ababx'
'x'.padStart(4, 'ab') // 'abax'

'x'.padEnd(5, 'ab') // 'xabab'
'x'.padEnd(4, 'ab') // 'xaba'

 

  10. 模板字符串

//傳統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

 

  11. 模板編譯

  比較複雜,用到時查閱相關例子

 

2、正則的擴展

   在ES5中,RegExp構造函數的參數有兩種狀況。

  第一種狀況是,參數是字符串,這時第二個參數表示正則表達式的修飾符(flag)。

  flag:

g ---表示全局模式,及模式將應用與全部字符串,而非發現的第一個匹配項的大小寫
i ---表示不區分別大小寫模式,即在肯定匹配時忽略模式與字符串的大小寫
m---表示多行模式,即在到達一行文本末尾時還會繼續查找下一行中是否存在模式匹配的項

  未完待續。。。

3、數值的擴展

  1. 二進制和八進制表示法

  ES6提供了二進制和八進制數值的新的寫法,分別用前綴0b(或0B)和0o(或0O)表示。

0b111110111 === 503 // true
0o767 === 503 // true

 

  若是要將0b0o前綴的字符串數值轉爲十進制,要使用Number方法。

Number('0b111')  // 7
Number('0o10')  // 8

 

  2. Number.isFinite(), Number.isNaN()

  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

 

  3. Number.parseInt(), Number.parseFloat()

  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

  4. Number.isInteger()

  Number.isInteger()用來判斷一個值是否爲整數。須要注意的是,在JavaScript內部,整數和浮點數是一樣的儲存方法,因此3和3.0被視爲同一個值。

  5. Number.EPSILON

  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

  6. 安全整數和Number.isSafeInteger() 

  用來判斷一個整數是否落在-2^532^53之間

  7. Math對象的擴展

  Math.trunc():用於去除一個數的小數部分,返回整數部分。

  對於非數值,Math.trunc內部使用Number方法將其先轉爲數值。

  對於空值和沒法截取整數的值,返回NaN。

  Math.sign():判斷一個數究竟是正數、負數、仍是零。

  它會返回五種值:

  • 參數爲正數,返回+1;
  • 參數爲負數,返回-1;
  • 參數爲0,返回0;
  • 參數爲-0,返回-0;
  • 其餘值,返回NaN。

  Math.cbrt():計算一個數的立方根

  未完待續。。。

  8. 指數運算符

  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;

 

3、數組的擴展

  1. Array.from() 

  用於將兩類對象轉爲真正的數組:相似數組的對象(array-like object)和可遍歷(iterable)的對象(包括ES6新增的數據結構Set和Map)。

  2.Array.of()

  將一組值,轉換爲數組

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老是返回參數值組成的數組。若是沒有參數,就返回一個空數組。

  3. 數組實例的copyWithin()

  4. 數組實例的find()和findIndex()

  數組實例的find方法,用於找出第一個符合條件的數組成員。它的參數是一個回調函數,全部數組成員依次執行該回調函數,直到找出第一個返回值爲true的成員,而後返回該成員。若是沒有符合條件的成員,則返回undefined

  5. 數組實例的fill()

  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']

 

  6. 數組實例的entries(),keys()和values() 

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']

 

  7. 數組實例的includes() 

  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

 

  8. 數組的空位

  數組的空位指,數組的某一個位置沒有任何值。好比,Array構造函數返回的數組都是空位。

Array(3) // [, , ,]

 

  注意,空位不是undefined,一個位置的值等於undefined,依然是有值的。空位是沒有任何值,in運算符能夠說明這一點。

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

 

  因爲空位的處理規則很是不統一,因此建議避免出現空位。

  9. ES6 中的 Set、Map 和 WeakMap

  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);
}
相關文章
相關標籤/搜索