日期:2014-05-16  浏览次数:20550 次

W3C Group的JavaScript1.7新特性介绍
在介绍完JavaScript1.6的新特性之后,W3C Group继续为大家介绍JavaScript1.7,JavaScript1.7带来了一系列的新特性,除了向下兼容javascript1.6之外,还包括生成器、迭代器、数组领悟、let 表达式,以及解构赋值等重要特性!

浏览器支持:

Firefox 2 Beta 1或以上版本

如何使用JavaScript1.7

如果你想使用Javascript1.7的新特性,你只需要在写Script标签的时候引入javascript1.7的版本号即可,如:

<script type="application/javascript;version=1.7"/>

注意:"yield" 和 "let"是javascript1.7中的两个新特性,请不要当作变量名或函数名使用!

下面我们介绍一下javascript1.7给我们带来的这些新特性!

生成器和迭代器

每当开发那些涉及到迭代算法(如对列表的迭代或对同一数据集进行相同的演算)的代码时,通常都需要声明一些变量,并在整个计算过程中都保留它们的值。一般来说,你还需要使用一个回调函数来获得迭代算法的中间值。
生成器

下面这个迭代算法计算了斐波那契数列:

function do_callback(num) {
document.write(num + "<br>\n");
}

function fib() {
var i = 0, j = 1, n = 0;
while (n < 10) {
do_callback(i);
var t = i;
i = j;
j += t;
n++;
}
}

fib();

这段代码使用了一个回调函数,来机械地执行算法每一步迭代的操作。这里,每一个斐波那契数都被简单地打印在控制台上。

使用生成器和迭代器,可以提供一个更新更好的方法。现在就让我们来看看使用了生成器的斐波那契数列:

function fib() {
var i = 0, j = 1;
while (true) {
yield i;
var t = i;
i = j;
j += t;
}
}

var g = fib();
for (var i = 0; i < 10; i++) {
document.write(g.next() + "<br>\n");
}

包含 yield 关键字的函数,就是一个生成器。当你调用它时,它的真正参数就会绑定到实际的变量上,但它自身其实并不做实际的计算,而是返回一个生成器-迭代器(generator-iterator)。每调用一次该生成器-迭代器的 next() 方法就再执行一次迭代算法。yield 关键字指定了每一步的值,就像生成器-迭代器版的 return 一样,指出了算法的每次迭代之间的边界。你每调用一次 next(),生成器代码就从 yield 以下的语句处恢复。

你可以重复调用一个生成器-迭代器的 next() 方法来使它转动,直到到达你期望的结果条件。在这个例子中,我们只需不停地调用 g.next(),就可以获得任意多的斐波那契数,直到满足我们所需要的结果个数。


从指定位置恢复生成器-迭代器

一个生成器在被调用其 next() 方法启动之后,你可以使用 send() 方法传递一个指定的的值,作为上一个 yield 的结果。这个生成器将返回后续 yield 的操作数。

你无法强制生成器从某个位置启动,在你 send() 一个指定的值给生成器之前,你必须先以 next() 启动它。
注意: 有意思的是,调用 send(undefined) 与调用 next() 是等价的。不过,用任何除 undefined 之外的值调用 send() 启动一个刚刚创建的生成器将引发 TypeError 异常。


生成器的异常

通过调用生成器的 throw() 方法并传递异常值,你可以强制生成器抛出异常。此异常将从该生成器当前挂起的上下文中被抛出,就好像在当前被挂起的 yield 中插入了一个 throw value 语句。

如果在抛出异常的过程中没有遇到 yield,那么该异常将被通过调用 throw() 传播,且后续的 next() 调用将导致 StopIteration 异常抛出。
关闭生成器

生成器的 close() 方法能强行关闭生成器自身。关闭生成器的效果如下:

1. 运行这个生成器函数中活动的 finally 语句。
2. 一旦 finally 语句抛出任何除 StopIteration 之外的异常,该异常被传播给 close() 方法的调用者。
3. 该生成器终结。

生成器示例

这段代码执行了一个每 100 次循环 yield 一次的生成器。

var gen = generator();

function driveGenerator() {
if (gen.next()) {
window.setTimeout(driveGenerator, 0);
} else {
gen.close();
}
}

function generator() {
while (i < something) {
/** 工作 **/

++i;
/** 100 循环 yield 一次 **/
if ((i % 100) == 0) {
yield true;
}
}

yield false;
}

迭代器

迭代器可以让你迭代数据,是一种特殊的对象。

在常规的用法中,迭代器对象是“不可见”的,你不需要显示地操作它们。取而代之,使用 JavaScript 的 for...in 和 for each...in 语句 自然地在对象的键、值之上循环。

var objectWithIterator = getObjectSomehow();

for (var i in objectWithIterator)
{
document.write(objectWithIterator[i] + "<br>\n");
}

如果你想实现你自己的迭代器对象,或对直接操作迭代器有另外的需求,你就需要了解 next 方法、StopIteration 异常和 __iterator__ 方法了。

你可以通过调用 Iterator(对象名) 来为一个对象创建迭代器。调用一个对象的 __iterator__ 方法时,需要查找它的迭代器;当这个方法不存在时,创建一个默认的迭代器。默认迭代器会根据传统的 for...in 和 for each...in 模型产出该对象的属性。也可以提供一个自定义的迭代器,只需重载 __iterator__ 方法,使它返回你自定义的迭代器的一个实例即可。你可以使用 Iterator(对象) 从脚本中获取一个对象的迭代器,以避免直接访问 __iterator__ 的属性,因为只有前者才对数组起作用。

一旦你拥有了一个迭代器,你就能够轻松地获取对象中的下一项了,调用该迭代器的 next() 方法即可。对象中没有余下的数据时,抛出 StopIteration 异常。

这里有一个直接迭代器操作的简单示例:

var obj = {name:"Jack Bauer", username:"JackB", id:12345, agency:"CTU", region:"Los Angeles"};

var it = Iterator(obj);

try {
while (true) {
print