(接上篇)html
標準ES6特性git
6. 新的String方法/New String methodses6
7. 符號/Symbolsgithub
8. 字符串模板/Template stringschrome
新的String方法/New String methods數組
codePointAt() 和 String.fromCodePoint()
JS內部是以UTF-16的形式(每一個字符長度都固定爲16位元、2個字節)來存儲字符編碼的。就漢字來講,大部分的漢字均以2字節的形式來存儲便可,卻也有部分漢字須要有4個字節的長度來存儲(其codePoint/碼點大於0xFFFF),好比這個生僻字「𠮷」(注意不是「吉」),其Unicode碼點是0x20BB7(十進制爲134071),UTF-16碼點爲0xD842 0xDFB7(十進制爲55362 57271)。
咱們若是對這種字符使用常規的 charAt(0) 和 String.fromCharCode() ,將沒法得到正確的碼點/字符:瀏覽器
var s = "𠮷", a = s.charCodeAt(0), //55362,即前兩個字節的碼點 b = String.fromCharCode(0x20BB7); //亂碼字符
爲解決此問題,ES6推出了 codePointAt() 和 String.fromCodePoint() 這兩個字符串方法,前者能夠順利獲取字符的Unicode碼點,後者可由已知碼點得到對應字符:ide
var s = "𠮷", a = s.codePointAt(0), //134071 b = String.fromCodePoint(0x20BB7); //"𠮷"
該方法的測試比較麻煩,由於常規是命令行界面是GBK編碼的,即便使用「chcp 65001」口令切到UTF-8形式也沒法正常顯示上文提到的生僻字符。不過咱們能夠將代碼轉到瀏覽器(別用IE)上顯示:函數
var s = "𠮷", a = s.codePointAt(0), aa = s.charCodeAt(0), b = s.codePointAt(1), bb = s.charCodeAt(1), c = String.fromCodePoint(a), cc = String.fromCharCode(aa), d = String.fromCodePoint(b), dd = String.fromCharCode(bb); console.log("a: "+a+",aa: "+aa+",b: "+b+",bb: "+bb+",c: "+c+",cc: "+cc+",d: "+d+",dd: "+dd); var http = require('http'), fs = require('fs'); http.createServer(function(req,res) { res.writeHeader(200,{"Content-Type": "text/html"}); res.write('<!doctype html><html><head><meta charset="utf-8"><title>測試</title></head><body><div>'); res.write("a: "+a+",aa: "+aa+",b: "+b+",bb: "+bb+",c: "+c+",cc: "+cc+",d: "+d+",dd: "+dd); res.end("</div></body></html>"); }).listen(1337);
接着咱們訪問地址 http://127.0.0.1:1337/ 可看到以下內容:測試
startsWith(),endsWith() 和 includes()
常規咱們會使用 s.indexOf() 來檢測一個字符串裏是否含有某段字符串。ES6提供了3個新的字符串檢索方法,其中 startsWith() 和 endsWith() 分別用於從頭部/尾部開始匹配字符串片斷,includes()則沒有位置限定,它們都返回boolean值。這三個方法都很好理解,直接上例子吧:
var str = 'To be, or not to be, that is the question.'; console.log(str.startsWith('To be')); //true console.log(str.endsWith('question.')); //true console.log(str.includes('not to be')); //true
這三個方法均支持第二個參數,表示開始搜索的位置:
var str = 'To be, or not to be, that is the question.'; console.log(str.startsWith('To be',1)); //false console.log(str.endsWith('To',2)); //true console.log(str.includes('not to be',1)); //true
注意endsWith()加上第二個參數後,表示匹配從開始到參數索引位置結束的字符串。
repeat()
repeat()返回一個新字符串,表示將原字符串重複n次:
var str = "x".repeat(3); console.log(str); //xxx
normalize()
該方法可將所給字符串轉化爲Unicode標準化字符:
var n1 = '\uD842\uDFB7'.normalize(); //𠮷
這裏有個有趣的例子——爲了表示語調和重音符號,Unicode提供了兩種方法。一種是直接提供帶重音符號的字符,好比Ǒ(\u01D1)。另外一種是提供合成符號(combining character),即原字符與重音符號的合成,兩個字符合成一個字符,好比O(\u004F)和ˇ(\u030C)合成Ǒ(\u004F\u030C)。
這兩種表示方法,在視覺和語義上都等價,可是JavaScript不能識別:
console.log('\u01D1'==='\u004F\u030C'); //false console.log('\u01D1'.length); // 1 console.log('\u004F\u030C'.length); // 2
上面代碼表示,JavaScript將合成字符視爲兩個字符,致使兩種表示方法不相等。使用normalize()方法能夠解決該問題:
var n1 = '\u01D1'.normalize() ; var n2 = '\u004F\u030C'.normalize(); alert(n1===n2); //true 注意這裏僅僅是在chrome爲true,但在iojs裏是false,由於iojs默認沒有自帶Intl,須要安裝的童鞋能夠查看這裏
normalize方法能夠接受四個參數:
NFC,默認參數,表示「標準等價合成」(Normalization Form Canonical Composition),返回多個簡單字符的合成字符。所謂「標準等價」指的是視覺和語義上的等價。
NFD,表示「標準等價分解」(Normalization Form Canonical Decomposition),即在標準等價的前提下,返回合成字符分解的多個簡單字符。
NFKC,表示「兼容等價合成」(Normalization Form Compatibility Composition),返回合成字符。所謂「兼容等價」指的是語義上存在等價,但視覺上不等價,好比「囍」和「喜喜」(固然這裏只是舉例子,normalize只適用於歐洲文字,解決法語的重音符號之類的問題)。
NFKD,表示「兼容等價分解」(Normalization Form Compatibility Decomposition),即在兼容等價的前提下,返回合成字符分解的多個簡單字符。
'\u004F\u030C'.normalize(NFC).length // 1 '\u004F\u030C'.normalize(NFD).length // 2
符號/Symbols
codePointAt() 和 String.fromCodePoint()
ES6引入了一種新的原始數據類型Symbol,表示獨一無二的ID。它經過Symbol函數生成:
var symbol1 = Symbol(); console.log(typeof symbol); // "symbol"
Symbol函數能夠接受一個字符串做爲參數,表示Symbol實例的名稱。須要注意的是Symbol實例均是獨一無2、不相等的:
var symbolA = Symbol('Test'); var symbolB = Symbol('Test'); console.log(symbolA===symbolB); //false
注意,Symbol函數前不能使用new命令,不然會報錯。這是由於生成的Symbol是一個原始類型的值,不是對象。若是你的確想生成一個Symbol包裝對象,應使用Object() 方法:
var sym = Symbol("foo"); typeof sym; // "symbol" var symObj = Object(sym); typeof symObj; // "object"
常規咱們把Symbol實例做爲某個對象的屬性名字,由於它是獨一無二的,能夠有效防止對象屬性被污染:
var syma = Symbol('test'); var symb = Symbol('test'); var aag = {}; aag[syma] = 123; aag[symb] = 456; console.log(aag[syma]); //123
另外一個須要瞭解的是Symbol實例做爲對象屬性是不可被枚舉的,但咱們能夠經過 Object.getOwnPropertySymbols() 來獲取它們:
var syma = Symbol('a'); var symb = Symbol('b'); var obj = {}; obj[syma] = 123; obj[symb] = 456; obj["c"] = 789; for(var i in obj) console.log(i+":"+obj[i]); //只輸出"c:789" var objectSymbols = Object.getOwnPropertySymbols(obj); console.log(objectSymbols.length); // 2 console.log(objectSymbols[0]); // Symbol(a) for(var i in objectSymbols) console.log( i +":"+ objectSymbols[i].toString()); //注意把Symbol實例轉爲字符串得使用.toString()方法 //0:Symbol(a) //1:Symbol(b)
除了常規建立獨一無二的Symbol實例,咱們也能夠經過 Symbol.for() 來建立可共享的Symbol實例。經過Symbol.for()建立的Symbol實例,咱們可使用 Symbol.keyFor() 獲取它的鍵名:
var syma = Symbol('a'); var symaa = Symbol('a'); var symb = Symbol.for('b'); var symbb = Symbol.for('b'); console.log(syma===symaa); //false console.log(symb===symbb); //true console.log(Symbol.keyFor(symb)); //b
Symbol除了可做爲對象的某個獨一無二的、不可枚舉的屬性,還有一個用處是可用於描述:
var obj = {}; var descript = Symbol.for('這是一個有趣的對象'); obj[descript] = Symbol.keyFor(descript); console.log(obj[descript]); //'這是一個有趣的對象'
字符串模板/Template strings
模板字符串(template string)是加強版的字符串,用反引號(`)標識(注意不是單引號)。它能夠看成普通字符串使用,也能夠用來定義多行字符串,或者在字符串中嵌入變量和公式等東西:
console.log(`string text line 1 //多行字符串 string text line 2`); //string text line 1 //string text line 2 // 字符串中嵌入變量 var name = "Bob", time = "today"; console.log(`Hello ${name}, how are you ${time}?`); //Hello Bob, how are you today? //花括號內可進行計算 var param_a = 1, param_b = 2; var obj = {c:3}; console.log(`the result is ${param_a + param_b + obj.c}`); //the result is 6
模板字符串使得字符串與變量的結合,變得容易。下面是一個例子:
if (x > MAX) { throw new Error(`Most ${MAX} allowed: ${x}!`); // 傳統寫法爲'Most '+MAX+' allowed: '+x+'!' }
模板字符串能夠緊跟在一個函數名後面,該函數將被調用來處理這個模板字符串:
var a = 5; var b = 10; function tag(s, v1, v2) { console.log(s[0]); console.log(s[1]); console.log(v1); console.log(v2); } tag`Hello ${ a + b } world ${ a * b}`; // "Hello " // " world " // 15 // 50
與常規的函數不一樣,Templat函數所接收到的參數比較另類,像上方的函數tag依次接受三個參數。第一個參數是一個數組,該數組的成員是模板字符串中那些沒有變量替換的部分,也就是說,變量替換隻發生在數組的第一個成員與第二個成員之間、第二個成員與第三個成員之間,以此類推。第一個參數以後的參數,都是模板字符串各個變量被替換後的值
也就是說,tag函數實際的參數以下:
tag(['Hello ', ' world '], 15, 50)
下面是一個更復雜的例子,展現瞭如何將各個參數按照原來的位置拼合回去:
var total = 30; var msg = passthru`The total is ${total} (${total*1.05} with tax)`; function passthru(literals) { var result = ""; var i = 0; while (i < literals.length) { result += literals[i++]; if (i < arguments.length) { result += arguments[i]; } } return result; } msg // "The total is 30 (31.5 with tax)"
另外模板字符串還有一個 String.raw() 方法,每每用來充當模板字符串的處理函數,返回字符串被轉義前的原始格式:
console.log(String.raw`Hi\n${2+3}!`); // "Hi\n5!" console.log(String.raw`Hi\u000A!`); // 'Hi\u000A!'
注:本文大部份內容參考自阮一峯老師的ES6入門,但本文實例已事先對全部代碼進行了校訂(包括在io.js上的兼容性、代碼錯誤的堪正,以及部分未說起特性方法的補漏)。
就此咱們便介紹了io.js上所支持的所有ES6特性,共勉~