[译]Node中的ES6特性
原文: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
和const
Map和
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