w3ctech:ECMAScript6——下一代Javascript标准
介绍
ECMAScript6是下一代Javascript标准,这个标准将在2015年6月得到批准。ES6是Javascript的一个重大的更新,并且是自2009年发布ES5以来的第一次更新。 它将会在主要的Javascript引擎实现以下新的特性。
Arrows(箭头函数)
ES6允许使用“箭头”(=>)定义函数。在语法上类似于C#、Java8和CoffeeScript的相关特性。它们同时支持表达式和语句体,和函数不同的是, 箭头在上下文中共享相同的this关键字。
// 表达式
var odds = evens.map(v => v + 1);
var nums = evens.map((v, i) => v + i);
// 语句体
nums.forEach(v => {
if (v % 5 === 0)
fives.push(v);
});
// this关键字
var bob = {
_name: "Bob",
_friends: [],
printFriends() {
this._friends.forEach(f =>
console.log(this._name + " knows " + f));
}
}
Classe结构
相对于目前使用的基于原型的面向对象模式而言,ES6中的class做法是一个简单的语法糖。它有一个方便的申明模式,并且鼓励互操作性。 class支持基于原型的继承、super调用、实例和静态方法和构造函数。
class SkinnedMesh extends THREE.Mesh {
//构造函数
constructor(geometry, materials) {
super(geometry, materials);
this.idMatrix = SkinnedMesh.defaultMatrix();
this.bones = [];
this.boneMatrices = [];
//...
}
update(camera) {
//...
super.update();
}
//静态方法
static defaultMatrix() {
return new THREE.Matrix4();
}
}
在上面的代码中,ES6使用constructor方法代替ES5的构造函数。
增强的Object对象
Object对象的增强ES6允许直接写入变量和函数,作为对象的属性和方法。这样的书写更加简洁。
var obj = {
// __proto__
__proto__: theProtoObj,
// 对 ‘handler: handler’ 的简化版
handler,
// 方法
toString() {
// Super calls
return "d " + super.toString();
},
// 计算(动态)属性名称
[ 'prop_' + (() => 42)() ]: 42
};
模板字符串
模板字符串提供构造字符串的语法糖,这种用法类似perl,python中的插值特征功能。 可选地,可以添加一个标签允许自定义字符串建设,避免注入攻击或从字符串构造更高层次数据结构的内容。
// 基本的字符串创建
`In JavaScript '\n' is a line-feed.`
// 多行字符串
`In JavaScript this is
not legal.`
// 构建DOM查询
var name = "Bob", time = "today";
`Hello ${name}, how are you ${time}?`
GET`http://foo.org/bar?a=${a}&b=${b}
X-Credentials: ${credentials}
{ "foo": ${foo},
"bar": ${bar}}`(myOnReadyStateChangeHandler);
Let 和 Const操作符
ES6新增了let命令,用来声明变量。它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效。 const也用来声明变量,但是声明的是常量。一旦声明,常量的值就不能改变。
function f() {
{
let x;
{
// okay, block scoped name
const x = "sneaky";
// error, const
x = "foo";
}
// error, already declared in block
let x = "inner";
}
}
For...of循环
JavaScript原有的for...in循环,只能获得对象的键名,不能直接获取键值。ES6提供for...of循环,允许遍历获得键值
let fibonacci = {
[Symbol.iterator]() {
let pre = 0, cur = 1;
return {
next() {
[pre, cur] = [cur, pre + cur];
return { done: false, value: cur }
}
}
}
}
for (var n of fibonacci) {
// truncate the sequence at 1000
if (n > 1000)
break;
print(n);
}
Generators
ES6草案定义的generator函数,需要在function关键字后面,加一个星号。然后,函数内部使用yield语句,定义遍历器的每个成员。
yield有点类似于return语句,都能返回一个值。区别在于每次遇到yield,函数返回紧跟在yield后面的那个表达式的值,然后暂停执行,下一次从该位置继续向后执行,而return语句不具备位置记忆的功能。
var fibonacci = {
[Symbol.iterator]: function*() {
var pre = 0, cur = 1;
for (;;) {
var temp = pre;
pre = cur;
cur += temp;
yield cur;
}
}
}
for (var n of fibonacci) {
// truncate the sequence at 1000
if (n > 1000)
break;
print(n);
}
Modules 模块
-
基本用法
ES6允许定义模块。也就是说,允许一个JavaScript脚本文件调用另一个脚本文件。
假设有一个circle.js,它是一个单独模块。
// circle.js export function area(radius) { return Math.PI * radius * radius; } export function circumference(radius) { return 2 * Math.PI * radius; }
然后,main.js引用这个模块。
// main.js import { area, circumference } from 'circle'; console.log("圆面积:" + area(4)); console.log("圆周长:" + circumference(14));
另一种写法是整体加载circle.js。
// main.js module circle from 'circle'; console.log("圆面积:" + circle.area(4)); console.log("圆周长:" + circle.circumference(14));
-
模块的继承
一个模块也可以继承另一个模块。
// circleplus.js export * from 'circle'; export var e = 2.71828182846; export default function(x) { return Math.exp(x); }
加载上面的模块。
// main.js module math from "circleplus"; import exp from "circleplus"; console.log(exp(math.pi);
-
模块的默认方法
还可以为模块定义默认方法。
// circleplus.js export default function(x) { return Math.exp(x); }