[译]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"
  • letconst
  • 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.isNaNNumber.isFinite,可是还不支持Number.toIntegerNumber.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脚本实现的.

参考

posted @ 2012-10-24 20:53  紫云飞  阅读(4766)  评论(0编辑  收藏  举报