ECMAScript 6,也称为 ECMAScript 2015,是 ECMAScript 标准的最新版本。 ES6 是该语言的重大更新,也是自 2009 年 ES5 标准化以来该语言的首次更新。这些功能目前正在主要 JavaScript 引擎中实现。
有关 ECMAScript 6 语言的完整规范,请参阅 ES6 标准。
ES6 包含以下新特性:
箭头是使用=>
语法的函数简写。它们在语法上与 C#、Java 8 和 CoffeeScript 中的相关功能相似。它们支持语句块体以及返回表达式值的表达式体。与函数不同,箭头与其周围的代码共享相同的词汇this
。
// Expression bodies
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 } ) ) ;
// Statement bodies
nums . forEach ( v => {
if ( v % 5 === 0 )
fives . push ( v ) ;
} ) ;
// Lexical this
var bob = {
_name : "Bob" ,
_friends : [ ] ,
printFriends ( ) {
this . _friends . forEach ( f =>
console . log ( this . _name + " knows " + f ) ) ;
}
}
更多信息:MDN 箭头函数
ES6 类是基于原型的 OO 模式的简单糖衣。拥有单一方便的声明形式使类模式更易于使用,并鼓励互操作性。类支持基于原型的继承、超级调用、实例和静态方法以及构造函数。
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 ( ) ;
}
}
更多信息:MDN 类
对象文字经过扩展以支持在构造时设置原型、 foo: foo
赋值、定义方法、进行超级调用以及使用表达式计算属性名称。总之,这些还使对象文字和类声明更加紧密地结合在一起,并使基于对象的设计受益于一些相同的便利。
var obj = {
// __proto__
__proto__ : theProtoObj ,
// Shorthand for ‘handler: handler’
handler ,
// Methods
toString ( ) {
// Super calls
return "d " + super . toString ( ) ;
} ,
// Computed (dynamic) property names
[ 'prop_' + ( ( ) => 42 ) ( ) ] : 42
} ;
详细信息:MDN 语法和类型:对象文字
模板字符串提供了用于构造字符串的语法糖。这类似于 Perl、Python 等中的字符串插值功能。或者,可以添加标签以允许自定义字符串构造,避免注入攻击或从字符串内容构造更高级别的数据结构。
// Basic literal string creation
`In JavaScript 'n' is a line-feed.`
// Multiline strings
`In JavaScript this is
not legal.`
// String interpolation
var name = "Bob" , time = "today" ;
`Hello ${ name } , how are you ${ time } ?`
// Construct an HTTP request prefix is used to interpret the replacements and construction
POST `http://foo.org/bar?a= ${ a } &b= ${ b }
Content-Type: application/json
X-Credentials: ${ credentials }
{ "foo": ${ foo } ,
"bar": ${ bar } }` ( myOnReadyStateChangeHandler ) ;
详细信息:MDN 模板字符串
解构允许使用模式匹配进行绑定,并支持匹配数组和对象。解构是失败软的,类似于标准对象查找foo["bar"]
,在未找到时生成undefined
值。
// list matching
var [ a , , b ] = [ 1 , 2 , 3 ] ;
// object matching
var { op : a , lhs : { op : b } , rhs : c }
= getASTNode ( )
// object matching shorthand
// binds `op`, `lhs` and `rhs` in scope
var { op , lhs , rhs } = getASTNode ( )
// Can be used in parameter position
function g ( { name : x } ) {
console . log ( x ) ;
}
g ( { name : 5 } )
// Fail-soft destructuring
var [ a ] = [ ] ;
a === undefined ;
// Fail-soft destructuring with defaults
var [ a = 1 ] = [ ] ;
a === 1 ;
详细信息:MDN 解构作业
被调用者评估的默认参数值。将数组转换为函数调用中的连续参数。将尾随参数绑定到数组。休息取代了arguments
的需要,并更直接地解决常见情况。
function f ( x , y = 12 ) {
// y is 12 if not passed (or passed as undefined)
return x + y ;
}
f ( 3 ) == 15
function f ( x , ... y ) {
// y is an Array
return x * y . length ;
}
f ( 3 , "hello" , true ) == 6
function f ( x , y , z ) {
return x + y + z ;
}
// Pass each elem of array as argument
f ( ... [ 1 , 2 , 3 ] ) == 6
更多 MDN 信息:默认参数、Rest 参数、Spread 运算符
块范围的绑定构造。 let
是新的var
。 const
是单一赋值。静态限制阻止在分配之前使用。
function f ( ) {
{
let x ;
{
// okay, block scoped name
const x = "sneaky" ;
// error, const
x = "foo" ;
}
// error, already declared in block
let x = "inner" ;
}
}
更多 MDN 信息:let 语句、const 语句
迭代器对象支持自定义迭代,如 CLR IEnumerable 或 Java Iterable。使用for..of
将for..in
泛化为基于自定义迭代器的迭代。不需要实现数组,从而启用 LINQ 等惰性设计模式。
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 ;
console . log ( n ) ;
}
迭代基于这些鸭子类型接口(仅使用 TypeScript 类型语法进行说明):
interface IteratorResult {
done : boolean ;
value : any ;
}
interface Iterator {
next ( ) : IteratorResult ;
}
interface Iterable {
[ Symbol . iterator ] ( ) : Iterator
}
更多信息:MDN for...of
生成器使用function*
和yield
简化了迭代器的编写。声明为 function* 的函数返回一个 Generator 实例。生成器是迭代器的子类型,其中包括额外的next
和throw
。这些使值能够流回生成器,因此yield
是一种返回值(或抛出)的表达式形式。
注意:也可用于启用类似“等待”的异步编程,另请参阅 ES7 await
提案。
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 ;
console . log ( n ) ;
}
生成器接口是(仅使用 TypeScript 类型语法进行说明):
interface Generator extends Iterator {
next ( value ?: any ) : IteratorResult ;
throw ( exception : any ) ;
}
更多信息:MDN 迭代协议
支持完整 Unicode 的不间断添加,包括字符串中的新 Unicode 文字形式和用于处理代码点的新 RegExp u
模式,以及用于在 21 位代码点级别处理字符串的新 API。这些新增功能支持用 JavaScript 构建全局应用程序。
// same as ES5.1
"?" . length == 2
// new RegExp behaviour, opt-in ‘u’
"?" . match ( / . / u ) [ 0 ] . length == 2
// new form
"u{20BB7}" == "?" == "uD842uDFB7"
// new String ops
"?" . codePointAt ( 0 ) == 0x20BB7
// for-of iterates code points
for ( var c of "?" ) {
console . log ( c ) ;
}
更多信息:MDN RegExp.prototype.unicode
对组件定义模块的语言级支持。将流行的 JavaScript 模块加载器(AMD、CommonJS)的模式编码化。由主机定义的默认加载程序定义的运行时行为。隐式异步模型 - 在请求的模块可用并处理之前不会执行任何代码。
// lib/math.js
export function sum ( x , y ) {
return x + y ;
}
export var pi = 3.141593 ;
// app.js
import * as math from "lib/math" ;
alert ( "2π = " + math . sum ( math . pi , math . pi ) ) ;
// otherApp.js
import { sum , pi } from "lib/math" ;
alert ( "2π = " + sum ( pi , pi ) ) ;
一些附加功能包括export default
和export *
:
// lib/mathplusplus.js
export * from "lib/math" ;
export var e = 2.71828182846 ;
export default function ( x ) {
return Math . log ( x ) ;
}
// app.js
import ln , { pi , e } from "lib/mathplusplus" ;
alert ( "2π = " + ln ( e ) * pi * 2 ) ;
更多 MDN 信息:导入声明、导出声明
模块加载器支持:
可以配置默认模块加载器,并且可以构造新的加载器以在隔离或受限上下文中评估和加载代码。
// Dynamic loading – ‘System’ is default loader
System . import ( 'lib/math' ) . then ( function ( m ) {
alert ( "2π = " + m . sum ( m . pi , m . pi ) ) ;
} ) ;
// Create execution sandboxes – new Loaders
var loader = new Loader ( {
global : fixup ( window ) // replace ‘console.log’
} ) ;
loader . eval ( "console.log('hello world!');" ) ;
// Directly manipulate module cache
System . get ( 'jquery' ) ;
System . set ( 'jquery' , Module ( { $ : $ } ) ) ; // WARNING: not yet finalized
适用于常见算法的高效数据结构。 WeakMaps 提供无泄漏的对象键侧表。
// Sets
var s = new Set ( ) ;
s . add ( "hello" ) . add ( "goodbye" ) . add ( "hello" ) ;
s . size === 2 ;
s . has ( "hello" ) === true ;
// Maps
var m = new Map ( ) ;
m . set ( "hello" , 42 ) ;
m . set ( s , 34 ) ;
m . get ( s ) == 34 ;
// Weak Maps
var wm = new WeakMap ( ) ;
wm . set ( s , { extra : 42 } ) ;
wm . size === undefined
// Weak Sets
var ws = new WeakSet ( ) ;
ws . add ( { data : 42 } ) ;
// Because the added object has no other references, it will not be held in the set
更多 MDN 信息:Map、Set、WeakMap、WeakSet
代理允许创建具有主机对象可用的全部行为的对象。可用于拦截、对象虚拟化、日志记录/分析等。
// Proxying a normal object
var target = { } ;
var handler = {
get : function ( receiver , name ) {
return `Hello, ${ name } !` ;
}
} ;
var p = new Proxy ( target , handler ) ;
p . world === 'Hello, world!' ;
// Proxying a function object
var target = function ( ) { return 'I am the target' ; } ;
var handler = {
apply : function ( receiver , ... args ) {
return 'I am the proxy' ;
}
} ;
var p = new Proxy ( target , handler ) ;
p ( ) === 'I am the proxy' ;
所有运行时级元操作都有可用的陷阱:
var handler =
{
get :... ,
set :... ,
has :... ,
deleteProperty :... ,
apply :... ,
construct :... ,
getOwnPropertyDescriptor :... ,
defineProperty :... ,
getPrototypeOf :... ,
setPrototypeOf :... ,
enumerate :... ,
ownKeys :... ,
preventExtensions :... ,
isExtensible :...
}
更多信息:MDN 代理
符号启用对象状态的访问控制。符号允许通过string
(如 ES5 中)或symbol
作为属性的键控。符号是一种新的原始类型。调试中使用的可选description
参数 - 但不是身份的一部分。符号是唯一的(如 gensym),但不是私有的,因为它们是通过Object.getOwnPropertySymbols
等反射功能公开的。
var MyClass = ( function ( ) {
// module scoped symbol
var key = Symbol ( "key" ) ;
function MyClass ( privateData ) {
this [ key ] = privateData ;
}
MyClass . prototype = {
doStuff : function ( ) {
... this [ key ] . . .
}
} ;
return MyClass ;
} ) ( ) ;
var c = new MyClass ( "hello" )
c [ "key" ] === undefined
更多信息:MDN 符号
在 ES6 中,像Array
、 Date
和 DOM Element
这样的内置函数可以被子类化。
名为Ctor
函数的对象构造现在使用两个阶段(都是虚拟调度的):
Ctor[@@create]
分配对象,安装任何特殊行为已知的@@create
符号可通过Symbol.create
获得。内置程序现在显式公开它们的@@create
。
// Pseudo-code of Array
class Array {
constructor ( ... args ) { /* ... */ }
static [ Symbol . create ] ( ) {
// Install special [[DefineOwnProperty]]
// to magically update 'length'
}
}
// User code of Array subclass
class MyArray extends Array {
constructor ( ... args ) { super ( ... args ) ; }
}
// Two-phase 'new':
// 1) Call @@create to allocate object
// 2) Invoke constructor on new instance
var arr = new MyArray ( ) ;
arr [ 1 ] = 12 ;
arr . length == 2
添加了许多新的库,包括核心数学库、数组转换助手、字符串助手和用于复制的 Object.assign。