ES6:JavaScript 新特性
2015-06-08 15:51
465 查看
我相信,在ECMAScript.next到来的时候,我们现在每天都在写的JavaScript代码将会发生巨大的变化.接下来的一年将会是令JavaScript开发者们兴奋的一年,越来越多的特性提案将被最终敲定,新一版本的JavaScript将会慢慢得到普及.本文中,我将会讲几个我个人很期待的,希望能在2013年或者更晚一点使用上的新特性.ECMAScript6兼容性表格,和Mozilla的ES6实现情况页面以及通过使用现代浏览器的最新版本(比如ChromeCanary,FirefoxAurora),来了解目前有哪些已经实现了的ES.next特性.在Canary中,记得要进入Traceur转换编译器(这里有一些单元测试的例子)来体验,以及一些shim项目比如ES6-Shim和HarmonyCollections,也实现了不少新特性.在Node.js(V8)中使用类,如果你想知道类和模块将会有什么联系,AlexRussell曾经写过一个很好的例子来说明这件事.JavaScript中有了类,并不意味着要把JavaScript变成Java.ES.next中的类只是我们已经熟悉的语义(比如函数,原型)的另外一种声明方式下面是用来定义一个widget的ES.next代码:classextendsconstructor(attributes){superthis}buildUI(){thisfunction};}}}下面是去糖(de-sugared)后的做法,也就是我们目前正在使用的方法:varfunctionfunctionWidget.call(thisthis}DropDownButton.prototype=Object.create(Widget.prototype,{constructor:{value:DropDownButton},buildUI:{value:functionthisfunction}}}});})(this);ES.next的写法的确让代码变的更可读.这里的我想,AMD和RequireJS应该被淘汰了.它们的确解决了一个实际存在的问题,但更理想的情况是,语言和运行环境应该内置类似的功能.模块的原生支持应该能够覆盖RequireJS80%的使用需求,从这一点上说,我们不再需要使用任何用户态(userland)的模块加载库了,至少在浏览器中是这样.
不过James的质疑是ES.next的模块是否是一个足够好的解决方案,他曾在六月份谈到过自己关于ES.next中模块的一些想法ES.next目前的实现情况
可以通过查看JuriyZaytsev总结的启用实验性JavaScript'选项以激活所有最新的的JavaScript特性.另外,许多ES.next特性还可以通过使用Google的
模块
我们已经习惯了将我们的代码分割成为更加便于管理的功能块.在ES.next中,一个模块(module)是就是一个
}一个模块实例就是一个被求过值的模块,它已经被链接到了其他的模块身上或者已经有了词法上的封装数据.下面是一个模块实例的例子:;
moduleUniverse{moduleMilkyWay{}};
moduleMilkyWay=;
moduleSolarSystem=Universe.MilkyWay.SolarSystem;
moduleMySystem=SolarSystem;一个
var;
exportfunctionconsole.log(,speed,direction);
}
exportexportfunction}
exportvarexportvar;
};一个模块可以使用
drive(),
再次用到上面导出相关的例子,我们现在可以有选择性的导入一些模块中的功能.比如我们可以导入
importdrivefromCar;还可以可以同时导入
miles:import{drive,miles}fromCar;下面,我们要讲一下模块加载器API的概念.模块加载器能够让我们动态的加载所需要的脚本.类似于
export声明过的东西.Loader.load(,functionconsole.log(car.drive(500,));},functionconsole.log(+err);});
关于类(class)我不打算在本文中过多的讲ES.next中的
function,至少是做了目前我们用
这些模块如何和AMD配合使用?
ES.next中的模块是朝着正确的方向走了一步吗?也许是吧.我自己的看法是:看相关的规范文档是一码事,实际上使用起来又是另一码事.在Harmonizr, RequireHM和 Traceur中可以体验新的模块语法,你会非常容易的熟悉这些语法,该语法可能会觉得有点像Python的感觉(比如我认为,如果一些功能有足够广泛的使用需求(比如模块),那么平台(也就是浏览器)就应该原生支持它们.而且,并不是只有我一个人这么觉得.JamesBurke,发明了AMD和RequireJS的人,也曾经说过:
兼容目前引擎的Module实现
Object.observe()
通过属性观察是我们经常会在MVC框架中看到的行为,它是数据绑定的一个重要组件,AngularJS和Ember.js都有自己的解决方案.这是一个非常重要的新功能,它不仅比目前所有框架的同类实现性能要好,而且还能更容易的观察纯原生对象.varlabel:,completed:false};Object.observe(todoModel,functionchanges.forEach(functionconsole.log(change);});});todoModel.label=;todoModel.completeBy=;deleteObject.observe马上将会在ChromeCanary中实现(需要开启"启用实验性JavaScript"选项).
兼容目前引擎的Object.observe()实现
RickWaldron的译者注:Firefox很早就有了一个类似的东西:这篇文章有关于
默认参数值
options=options||{};这样的语句了.该语法形式就是把一个初始值赋值给对应的形参名:function){console.log(caption);}addTodo();拥有默认参数值的形参只能放在形参列表的最右边:functionfunction,order=4){}functionthis){}已经实现该特性的浏览器:Firefox18+
块级作用域
块级作用域引入了两种新的声明形式,可以用它们定义一个只存在于某个语句块中的变量或常量.这两种新的声明关键字为:var,但定义的变量只存在于当前的语句块中
let类似,但声明的是一个只读的常量使用
var可以更容易的定义一个只在某个语句块中存在的局部变量,而不用担心它和函数体中其他部分的同名变量有冲突.在
var声明的变量和在
var声明的变量没什么差别,它们都拥有函数作用域,而不是块级作用域.
let(var1=1){alert(var1);//弹出1,var1是个块级作用域变量varvar2=2;}varvar3=3;alert(var2);//弹出2,虽然var2是在let语句内部声明的,但它仍然是个函数作用域内的变量,因为使用的是var声明alert(var3);//弹出3alert(var1);//抛出异常
实现const的浏览器:Firefox18+,Chrome24+,Safari6+,WebKit,Opera12+
Map
我想大部分读者已经熟悉了映射的概念,因为我们过去一直都是用纯对象来实现映射的.get()方法,可以获取到所存储的值.Map对象还有其他三个方法:
size():返回map中键值对的个数newm.set(,.length);m.get();m.has();m.delete'todo'm.has();已经实现Map的浏览器:Firefox18+NicholasZakas的
兼容目前引擎的Map实现
Set.prototype.size都从size()方法改成size访问器属性了.同时Map对象新添加的方法还有很多,clear()用来清空一个map,forEach()用来遍历一个map,还有items(),keys(),values()等.Set对象也类似,有不少作者没提到的方法,下面的Set小节我就不指出了.另外,在ES5中,在把对象当成映射来使用的时候,为了防止原型继承带来的问题(比如在twitter中,@__proto__能让浏览器卡死),可以用varhash=Object.create(null)代替varhash={};
Set
正如NicholasZakas在他的文章中所说,对于那些接触过Ruby和Python等其他语言的程序员来说,has(value)–返回一个布尔值,表明value这个值是否存在于这个set中.new//s有1,2,3三个元素.s.has(-Infinity);s.add(-Infinity);//s有1,2,3,-Infinity四个元素.s.has(-Infinity);s.deletes.has(-Infinity);Set对象的一个作用是用来降低过滤操作(filter方法)的复杂度.比如:functionvarnewreturnfunctionifseen.add(item);returntrue}});}这个利用Set来进行数组去重的函数的复杂度为O(n).而其他现有数组去重方法的复杂度几乎都为O(n^2).已经实现Set的浏览器:Firefox18,Chrome24+.NicholasZakas的
兼容目前引擎的Set实现
functionunique(array){return[vfor(vofSet(array))]}该函数使用到了ES6中的
>Array.from(newSet([1,1,2,2,3,4]));[1,2,3,4]甚至,借助于ES6中的
>[...newSet([1,1,2,2,3,4])];[1,2,3,4]