io.js入門(三)—— 所支持的ES6(下)

(接上篇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);
View Code

接着咱們訪問地址 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)"
View Code

 

另外模板字符串還有一個 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特性,共勉~

donate

相關文章
相關標籤/搜索