原文:http://dailyjs.com/2012/10/15/preparing-for-esnext/
Brendan Eich在Harmony之夢實現了一文中,講了一些Firefox已經實現的ES6新特性.令Node開發者興奮的是,V8也實現了其中不少的特性.
如何知道自己使用的Node支持哪些新特性:首先查看process.versions的值,
~ node -e 'console.log(process.versions)' { http_parser: '1.0',
node: '0.8.12',
v8: '3.11.10.22',
ares: '1.7.5-DEV',
uv: '0.8',
zlib: '1.2.3',
openssl: '1.0.0f' }
知道了V8的版本號,就可以在V8的更新日志中查找到該版本具體添加了哪些新特性.下面列出了Node目前支持的ES6特性:
- 塊級作用域
- typeof null等於"null"
let和constMap和WeakMap- 模塊
- 代理
Harmony相關選項
運行命令node --v8-options可以顯示出所有與V8相關的選項:
--harmony_typeof: 激活harmony中typeof的新特性(typeof null等於"null").(譯者注:相關提案已被拒絕,該選項未來應該會被刪除)
--harmony_scoping: 激活harmony中的塊級作用域
--harmony_modules: 激活harmony中的模塊
--harmony_proxies: 激活harmony中的代理(譯者注:和網絡中的代理服務器沒有任何關系)
--harmony_collections: 激活harmony中的集合類型(Set,Map,WeakMap)
--harmony: 激活上面所有的harmony特性(除了typeof)
只需要在運行腳本的時候加上所需選項即可:
node --harmony script.js
例子: typeof
--harmony_typeof選項比較特殊,因為它沒有被包含在--harmony中.這很有可能是因為harmony:typeof_null這項提案被拒絕了的原因.很多提案中的特性都有可能在規范完成之前被拒絕掉,如果你不確定某個特性目前的狀態,最好的辦法就是在ECMAScript DokuWiki上進行搜索.
如果啟用了該選項,typeof null === "null" 會返回true.
例子: 類型檢查
在沒有使用--harmony選項的情況下,Node也支持ES6特性Number.isNaN和Number.isFinite,可是還不支持Number.toInteger和Number.isInteger.
isNaN("x") //true,"x"會被轉換成NaN
Number.isNaN("x") //false
isFinite("1") //true,"1"會被轉換成1
Number.isFinite("1") //false
例子:塊級作用域
ES5中的嚴格模式修復了JavaScript一個重大的設計缺陷:缺失var的賦值語句會創建一個全局變量.ES6更進了一步,引入了可以創建塊級作用域變量的let.下面的例子必須使用命令node --use-strict --harmony來運行:
for (let i = 0; i < 3; i++) {
console.log('i:', i);
}
console.log(i);
最后的語句console.log(i),會拋出一個ReferenceError異常.因為變量i不存在於for語句外的作用域中.而且,假如你忘記了寫let,也不會誤創建一個全局變量,因為我們啟用了嚴格模式,那樣只會拋出ReferenceError異常.和let一樣,用const定義的常量也擁有塊級作用域.
例子: 集合
ES6添加了幾個新類型來存儲集合數據: Map, Set,和WeakMap. Map類型允許將任意對象值或原始值映射到另一個值上.聽起來像普通的對象,因為我們以前總用普通的對象來實現Map本來該做的事.千萬別混淆,它們是有區別的:
var assert = require('assert')
, m = new Map()
, key = { a: 'Test' }
, value = 'a test value' ; m.set(key, value); assert.equal(m.get(key), value);
這個例子表明了,map中的鍵是不會被轉換成字符串的,而對象會.
Node已經支持了Set類型,但目前還不能通過向構造函數傳入一個二維數組來進行set的初始化,也還不支持Set.prototype.size方法.
var assert = require('assert')
, s = new Set()
;
s.add('a');
assert.ok(s.has('a'));
WeakMap是一種擁有弱引用的map.因為WeakMap保持着對一個對象的弱引用,所以它的鍵不能被遍歷(譯者注:我的理解是,因為這個鍵指向的對象有可能已經不存在了,弱引用的意思就是只保存一個標識符或者說內存地址,那個內存地址的值是什么並不關心).優點是,當沒有其他值引用這個鍵所引用的對象時,垃圾回收器會清除那個對象.
WeakMap更節約內存,復雜度比O(n)還低.
Andy E去年發表過一篇文章:ES6 – a quick look at Weak Maps,談到了WeakMap對jQuery中的expando屬性的影響.
我嘗試創建過一些擁有循環引用的WeakMap實例,然后通過gc()強制執行垃圾回收(需要添加選項node --harmony --expose_gc),但是很難檢測出那些應該被垃圾回收的對象是否真的被刪除了:
代理
貌似Node目前實現的是舊的代理API,所以我認為還沒必要去研究它.新的代理API還沒有實現,因為我沒有在郵件列表或相關資料上看到任何消息.
生成器,類,宏
目前V8還不支持生成器(Generator), 類(class)以及宏(macro).這些特性仍處於激烈的討論當中,你可以在ECMAScript DokuWiki上了解詳情:
Andreas Rossberg說過V8的工程師還不打算實現生成器.
如果你現在就想嘗試一下宏,可以試試Mozilla最近發布的sweet.js (GitHub: mozilla / sweet.js, License: BSD, npm: sweet.js).這是一個命令行工具,可以將你寫的腳本"編譯"為JavaScript,類似於CoffeeScript.
解構(Destructuring)也已經被添加到了ECMAScript 6規范草案中.
所有的ES6 shim都沒有包含這些特性,因為有些特性是無法用舊版的ECMAScript腳本實現的.
參考
- Harmony of Dreams Come True by Brendan Eich
- MDN: Map
- MDN: Set
- MDN: WeakMap
- ES6 – a quick look at Weak Maps by Andy E
