简介
ECMAScript 6, 也被称为 ECMAScript 2015, 是ECMAScript标准的最新版本。ES6 是 js 语言的一次重大更新,也是2009年的标准 ES5 之后的第一次更新。这些功能在主要的 JavaScript 引擎中已实现。
有关ECMAScript 6语言的完整规范,请参阅ES6标准。
ES6 包括了以下新特性:(顺序进行改变,将重要特性提前)
- let + const
- arrows
- classes
- enhanced object literals
- template strings
- destructuring
- default + rest + spread
ECMAScript 6 特性
let + const
块状作用域
块状作用域绑定结构。let 是新的 var。const 定义常数。在定义前静态限制阻止使用(官方翻译:此两种操作符具有静态限制,可以防止出现“在赋值之前使用”的错误)。
function f() {
{
let x;
{
// ok,代码块内赋值
const x = "sneaky";
// 错误,常数不可赋值
x = "foo";
}
// 错误,块内已声明
let x = "inner";
}
}
说明:
1. 由于var 定义变量是全局的,通常我们都人为约定将所有变量及函数定义在文件头部,避免变量提升带来的问题;而 let 与 const 作用于块级作用域,不会带来变量提升的问题。
2. 大家一直在说块级作用域,那么块级作用域到底是什么?
在ES6 之前,作用域只有两种:全局作用域 和 函数作用域。顾名思义,分别作用域全局和函数体内部,而块级作用域是更小范围的作用域,也就是在一对{}
之间的范围。
arrows
箭头函数
箭头函数通过 =>语法是对 function 的缩写。它们在语法上类似于C#,Java 8和CoffeeScript。它们支持语句块体以及返回表达式值的表达式体。与functions不同,箭头函数体内的this对象,就是定义时所在的对象。并且不会因为运行时上下文发生改变而变化。
// 表达体
var odds = evens.map(v => v + 1);
var nums = evens.map((v, i) => v + i);
var pairs = evens.map(v => ({even: v, odd: v + 1}));
// 声明体
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));
}
}
说明:
1. =>根本没有自己的this,它的this是继承外面的,因此内部的this就是外层代码块的this。
2. 在ES6中, =>可以混合和匹配老的函数一起使用。当在一行代码中用了箭头函数,它就变成了一个表达式。它将内部进行处理并返回单个语句的结果。如果你超过了一行,将需要明确使用return。且在 => 中,对于单个参数,括号()是可选的,但当你超过一个参数的时候你就需要他们。
classes
重新定义类,语法糖
ES6 的类在基于原型模式的面向对象模式中只是简单的语法糖。它拥有单一方便的声明式表单使得类模式更易于使用,并富有互操作性。类支持基于原型的继承,父类调用,实例方法,静态方法和构造函数。
class SkinnedMesh extends THREE.Mesh {
constructor(geometry, materials) {
super(geometry, materials);
this.idMatrix = SkinnedMesh.defaultMatrix();
this.bones = [];
this.boneMatrices = [];
//...
}
update(camera) {
//...
super.update();
}
get boneCount() {
return this.bones.length;
}
set matrixType(matrixType) {
this.idMatrix = SkinnedMesh[matrixType]();
}
static defaultMatrix() {
return new THREE.Matrix4();
}
}
说明:
1. Class之间通过extends
关键字实现继承;
2. super
关键字,它指代父类的实例(即父类的this
对象)。子类必须在constructor
方法中调用super
方法,否则新建实例时会报错。这是因为子类没有自己的this
对象,而是继承父类的this
对象,然后对其进行加工。如果不调用super
方法,子类就得不到this
对象。
3. ES6的继承机制,实质是先创造父类的实例对象this
(所以必须先调用super
方法),然后再用子类的构造函数修改this
。
4. Javascript语言里,并没有了真正的类!class 仅仅是ES6 提供的语法糖。
enhanced object literals
增强对象字面量
扩展对象字面量,以支持在构建中设置原型,简化foo:foo arguments 表达,定义方法,使用父类调用以及使用表达式计算属性名等。并且,这些也将使对象字面量和类声明更紧密结合,也让基于对象的设计从中获益。
var obj = {
// 1. __proto__ :设置属性
__proto__: theProtoObj,
// 2. 简化 ‘handler: handler’
handler,
// 3. 方法简写
toString() {
// 覆盖父类方法
return "d " + super.toString();
},
// 4. 动态生成属性名
[ 'prop_' + (() => 42)() ]: 42
};
说明:
什么是对象字面量?将{}
赋值到一个变量 的定义对象的方式我们成为字面量。
上面源码中,4
显然是最有意思的一种写法,让我们可以使用变量定义对象中的键名;当然,ES5 中其实也同样支持,只是代码会更复杂,具体稍候补上。
template strings
模板字符串,语法糖
模板字符串为构造字符串提供语法糖。这很类似Perl, Python 等语言中的字符串插值方法。另外,可以选择性的添加标签以允许定制字符串构造,避免注入攻击或从字符串内容上构建更高级别的数据结构。
// 添加转义字符串
`In JavaScript '\n' is a line-feed.`
// 多行字符串
`In JavaScript this is
not legal.`
// 字符串插值
var name = "Bob", time = "today";
`Hello ${name}, how are you ${time}?`
// 构造HTTP请求前缀用于解释替换和构造
POST`http://foo.org/bar?a=${a}&b=${b}
Content-Type: application/json
X-Credentials: ${credentials}
{ "foo": ${foo},
"bar": ${bar}}`(myOnReadyStateChangeHandler);
说明:
格式:用反引号(\
)来标识起始,用${}
来引用变量
destructuring
解构
解构允许使用模式匹配进行绑定,并支持匹配数组和对象。解构支持失效弱化,类似标准对象foo["bar"]
,当未找到结果时输出 undefined
。
// list 匹配
var [a, , b] = [1,2,3];
// object 匹配
var { op: a, lhs: { op: b }, rhs: c }
= getASTNode()
// object 匹配缩写
// 在方法范围内绑定 `op`, `lhs` and `rhs`
var {op, lhs, rhs} = getASTNode()
// 用于参数定位
function g({name: x}) {
console.log(x);
}
g({name: 5})
// 失效弱化解构,结果查询不到时定义为 undefined
var [a] = [];
a === undefined;
// 具备默认值的失效弱化解构
var [a = 1] = [];
a === 1;
说明:
解构:按照一定模式,从数组和对象中提取值,对变量进行赋值;
还可以这样写:
let children = {type: 'people', number: 3}
let { type, number} = children
console.log(type, number) //people 3
default + rest + spread
默认参数+不定参数+参数展开
语法糖,语法糖,还是语法糖
支持由被调用函数进行求值的参数默认值。 在函数调用时可以将数组拆解为连续的多个参数。绑定多个参数到一个数组中。 不定参数(Rest)取代了arguments,并可更直接地应用于通常的用例中。
function f(x, y=12) {
// y 未传或传入undefined
return x + y;
}
f(3) == 15
function f(x, ...y) {
// y 是数组
return x * y.length;
}
f(3, "hello", true) == 6
function f(x, y, z) {
return x + y + z;
}
// 将传入数组的所有元素解析为参数
f(...[1,2,3]) == 6
说明:
上面三段代码已经非常直观的解释了ES6中方法参数的处理。
写了这么多,突然发现居然有中文版??!!(此处自行代入WTF脸。。)
默默地把中文版地址贴出来:ECMAScript 6 Features 中文版
以上,仅供参考。