ES6 包含了以下这些新特性:
Arrows 箭头函数Classes 类Enhanced Object Literals 增强的对象字面量Template Strings 模板字符串Destructuring 解构Default + Rest + Spread 默认参数+不定参数+参数展开Let + Const 操作符Iterators 迭代器 + For..Of 循环Generators 生成器Unicode 统一码Modules 模块Module Loaders 模块加载器Map + Set + Weakmap + Weakset 数据结构Proxies 代理Symbols 符号Subclassable Built-ins 可子类化内建对象Promises 对象Math + Number + String + Object APIsBinary and Octal Literals 二进制和八进制字面量Reflect 反射 APITail Calls 尾调用Arrows are a function shorthand using the => syntax.
They are syntactically similar to the related feature in C#, Java 8 and CoffeeScript.
They support both expression and statement bodies.
Unlike functions, arrows share the same lexical this as their surrounding code.
If an arrow is inside another function, it shares the “arguments” variable of its parent function.
Statement bodies
Lexical this
Lexical arguments
ES2015 classes are a simple sugar over the prototype-based OO pattern.
Having a single convenient declarative form makes class patterns easier to use, and encourages interoperability.
Classes support prototype-based inheritance, super calls, instance and static methods and constructors.
Object literals are extended to support setting the prototype at construction, shorthand for foo: foo assignments, defining methods and making super calls.
Together, these also bring object literals and class declarations closer together, and let object-based design benefit from some of the same conveniences.
The __proto__ property requires native support, and was deprecated in previous ECMAScript versions.
Most engines now support the property, but some do not.
Also, note that only web browsers are required to implement it, as it's in Annex B.
It is available in Node.
Template strings provide syntactic sugar for constructing strings.
This is similar to string interpolation features in Perl, Python and more.
Optionally, a tag can be added to allow the string construction to be customized, avoiding injection attacks or constructing higher level data structures from string contents.
Destructuring allows binding using pattern matching, with support for matching arrays and objects.
Destructuring is fail-soft, similar to standard object lookup foo["bar"], producing undefined values when not found.
object matching
object matching shorthand
parameter position
Callee-evaluated default parameter values.
Turn an array into consecutive arguments in a function call.
Bind trailing parameters to an array.
Rest replaces the need for arguments and addresses common cases more directly.
Block-scoped binding constructs.
let is the new var.
const is single-assignment.
Static restrictions prevent use before assignment.
function someFunction() { { let x; { // this is ok since it's a block scoped name const x = "beyond"; // error, was just defined with `const` above x = "bangs"; // bangs: 刘海 } // this is ok since it was declared with `let` x = "bar"; // error, already declared above in this block // 禁止重复定义 let x = "inner"; } }CLR(公共语言运行库,Common Language Runtime) 和 Java虚拟机 一样也是一个运行时环境,
是一个可由多种编程语言使用的运行环境。
CLR的核心功能包括:内存管理、程序集加载、安全性、异常处理和线程同步,
可由面向CLR的所有语言使用。
并保证应用和底层操作系统之间必要的分离。
CLR是.NET Framework的主要执行引擎。
Iterator objects enable custom iteration like CLR IEnumerable or Java Iterable.
Generalize for..in to custom iterator-based iteration with for..of.
Don’t require realizing an array, enabling lazy design patterns like LINQ.
for of 循环有很多优点:
1. 不像for...in一样只遍历键名(甚至包括原型链上的键 ???Excuse Me???)
2. 不像foreach不能跳出循环
3. for...of为各种数据结构提供了一个统一的遍历方法
什么是 duck-typed ?
“当看到一只鸟 走起来像鸭子、游起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为 鸭子。”我们并不关心对象是什么类型,到底是不是真正的鸭子,我们只关心行为。
Iteration is based on these duck-typed interfaces
(using TypeScript type syntax for exposition only)
(这儿只是用一下TypeScript的语法进行一下阐述而已啦~):
// 能够被迭代的对象,都要实现该方法interface Iterable { [Symbol.iterator](): Iterator} // 迭代器必须实现的方法 next()interface Iterator { next(): IteratorResult;} // next()方法必须返回的结果 属性interface IteratorResult { done: boolean; value: any; }In order to use Iterators you must include the Babel polyfill.
Shim. A shim is a library that brings a new API to an older environment, using only the means of that environment.
A polyfill is a piece of code (or plugin) that provides the technology that you, the developer, expect the browser to provide natively. Flattening the API landscape if you will.
翻译过来就是:
一个shim是一个库,它将一个新的API引入到一个旧的环境中,而且仅靠旧环境中已有的手段实现
一个polyfill就是一个只用在浏览器API上的shim.
我们通常的做法是先检查当前浏览器是否支持某个API,如果不支持的话就加载对应的polyfill.
然后新旧浏览器就都可以使用这个API了.
术语polyfill来自于一个家装产品Polyfilla:Polyfilla是一个英国产品,在美国称之为Spackling Paste(译者注:刮墙的,在中国称为腻子).
记住这一点就行:把旧的浏览器想象成为一面有了裂缝的墙.
这些[polyfills]会帮助我们把这面墙的裂缝抹平,还我们一个更好的光滑的墙壁(浏览器)
Paul Irish发布过一个Polyfills的总结页面“HTML5 Cross Browser Polyfills”.
es5-shim是一个shim(而不仅仅是polyfill)的例子,因为它既能在ECMAScript 3的引擎上实现了ECMAScript 5的新特性,
而且又能在Node.js上和在浏览器上有完全相同的表现(注意:因为它能在Node.js上使用,不光浏览器上,所以它不是polyfill).
for...of 访问了array的iterator,并调用了next()
对象要自己实现 迭代器
又一个给对象实现iterator的例子,然后,用for...of 迭代输出
Generators simplify iterator-authoring using function* and yield.
A function declared as function* returns a Generator instance.
Generators are subtypes of iterators which include additional next and throw.
These enable values to flow back into the generator, so yield is an expression form which returns a value (or throws).
Note: Can also be used to enable ‘await’-like async programming, see also ES7 await proposal.
The generator interface is (using TypeScript type syntax for exposition only):
interface Generator extends Iterator { next(value?: any): IteratorResult; throw(exception: any); }In order to use Generators you must include the Babel polyfill.
示例代码一:
(把上面对象的 iterator 复杂的实现过程 通过 Generator快速实现)
通过function* 和 yield 对一个对象 快速实现迭代器
示例代码二:
(把上面对象的 iterator 复杂的实现过程 通过 Generator快速实现)
Removed in Babel 6.0 ???Excuse Me???
Non-breaking additions to support full Unicode,
including new unicode literal form in strings and new RegExp u mode to handle code points,
as well as new APIs to process strings at the 21bit code points level.
These additions support building global apps in JavaScript.
RequireJS 遵循的是 AMD(异步模块定义) 规范,
SeaJS 遵循的是 CMD (通用模块定义)规范
AMD/CMD/CommonJs是JS模块化开发的标准,
目前对应的实现是RequireJs/SeaJs/nodeJs.
CommonJs主要针对服务端
服务器端一般采用同步加载文件,也就是说需要某个模块,服务器端便停下来,等待它加载再执行。
AMD/CMD主要针对浏览器端
而浏览器端要保证效率,需要采用异步加载,
这就需要一个预处理,提前将所需要的模块文件并行加载好。
AMD/CMD 虽然都是并行加载js文件,但还是有所区别的
AMD是预加载,在并行加载js文件同时,还会解析执行该模块
因为还需要执行,所以在加载某个模块前,这个模块的依赖模块也需要先加载完成
CMD是懒加载,虽然会一开始就并行加载js文件,但是不会执行,而是在需要的时候才执行。
AMD/CMD的优缺点: 一个的优点就是另一个的缺点
AMD优点:因为是预加载, 所以加载快速,尤其遇到多个大文件,
因为并行解析,所以同一时间可以解析多个文件。
AMD缺点:由于是并行加载,异步处理,加载顺序不确定,可能会造成一些麻烦,甚至为程序埋下超级大坑。 CMD优点:因为只有在使用的时候才会解析执行js文件,
因此,每个JS文件的执行顺序在代码中是有体现的,是可控的。
CMD缺点:由于是用到时才去加载,所以执行等待时间会叠加。
因为每个文件执行时是同步执行(串行执行),
因此时间是所有文件解析执行时间之和,尤其在文件较多较大时,这种缺点尤为明显。
如何使用? CommonJs的话,因为nodeJs就是它的实现,所以直接用node就行,也不用引入其他包。
AMD则是通过<script>标签引入RequireJs
CMD则是引入SeaJs
安装babel-cli搭建支持ES6的Node环境
babel-cli有两个主要的命令需要用到: babel:按照“.babelrc“文件转码js文件。 babel-node:提供一个支持ES6的REPL环境,支持Node的REPL环境的所有功能,可以直接运行ES6代码。
第1步: 安装 (全局安装)
npm install babel-cli -g第2步,配置(无)
第3步,使用
babel-cli工具自带一个babel-node命令,提供一个支持ES6的REPL环境。
它不但支持Node的REPL环境的所有功能,还可以直接运行ES6代码。
它不用单独安装,而是随babel-cli一起安装。
然后,在命令行, 执行babel-node就进入PEPL环境。
$ babel-node > (x => x + 6)(7) 13babel-node命令 还可以直接运行ES6脚本。
将上面的代码放入脚本文件es6_01.js,然后直接运行。
$ babel-node es6_01.js 13babel-node也可以安装在项目中
$ npm install --save-dev babel-cli然后,改写package.json
{ "scripts": { "script-name": "babel-node es6_01.js" } }上面代码中,使用babel-node替代node,这样script.js本身就不用做任何转码处理。
将ES6转码成ES5代码文件
该种方法使用babel命令进行转码。
babel命令需要使用“.babelrc“文件,其中会用到转码规则es2015,对应的模块是babel-preset-es2015,先要进行安装。
1. 在工作文件夹sg_es目录 中执行命令安装。
npm install babel-preset-es2015 --save-dev2. 安装完成后,在工作文件夹中创建文件”.babelrc“,内容为。
{ "presets": [ "es2015" ], "plugins": [] }3. 执行以下命令进行ES6到ES5的转码。
babel es6_01.js -o es5_01.js可以看到转码后的es5_01.js的内容,很方便。
Language-level support for modules for component definition.
Codifies patterns from popular JavaScript module loaders (AMD, CommonJS).
Runtime behaviour defined by a host-defined default loader.
Implicitly async model – no code executes until requested modules are available and processed.
// modules/es6_02_math.js export function sum(x, y) { return x + y; } export var PI = 3.141593; // es6_02_a.js 必须加 ./ import * as math from "./modules/es6_02_math"; console.log("2π = " + math.sum(math.pi, math.pi)); // 结果如下: // es6_02_b.js import {sum, pi} from "./modules/es6_02_math"; console.log("2π = " + sum(pi, pi)); // 结果如下:es6_02_a.js运行结果如下:
es6_02_b.js运行结果如下:
Some additional features include export default and export *:
位于modules目录下的es6_02_math_advance.js代码如下:
// modules/es6_02_math_advance.js// 必须要写 ./ export * from "./es6_02_math"; export var E = 2.71828182846 export default function(x) { return Math.exp(x) } // es6_02_c.js// 给 default 导出的匿名函数 起个名字 import exportFunction, {PI, E} from "./modules/es6_02_math_advance"var result = exportFunction(PI) console.log("e^π = " + result) // 结果如下:Babel can transpile ES2015 Modules to several different formats including Common.js, AMD, System, and UMD.
You can even create your own.
For more details see the modules docs.
es6_02_c.js运行结果如下: 万维网联盟(W3C) 网页 超文本 技术 工作 小组(WHATWG)Efficient data structures for common algorithms.
WeakMaps provides leak-free object-key’d side tables.
In order to support Maps, Sets, WeakMaps, and WeakSets in all environments you must include the Babel polyfill.
Proxies enable creation of objects with the full range of behaviors available to host objects.
Can be used for interception, object virtualization, logging/profiling, etc.
Proxying a normal object
Proxying a function object
There are traps available for all of the runtime-level meta-operations:
var handler = { // target.prop get: ..., // target.prop = value set: ..., // 'prop' in target has: ..., // delete target.prop deleteProperty: ..., // target(...args) apply: ..., // new target(...args) construct: ..., // Object.getOwnPropertyDescriptor(target, 'prop') getOwnPropertyDescriptor: ..., // Object.defineProperty(target, 'prop', descriptor) defineProperty: ..., // Object.getPrototypeOf(target), Reflect.getPrototypeOf(target), // target.__proto__, object.isPrototypeOf(target), object instanceof target getPrototypeOf: ..., // Object.setPrototypeOf(target), Reflect.setPrototypeOf(target) setPrototypeOf: ..., // for (let i in target) {} enumerate: ..., // Object.keys(target) ownKeys: ..., // Object.preventExtensions(target) preventExtensions: ..., // Object.isExtensible(target) isExtensible :... }Due to the limitations of ES5, Proxies cannot be transpiled or polyfilled.
See support in various JavaScript engines.
Symbols enable access control for object state.
Symbols allow properties to be keyed by either string (as in ES5) or symbol.
Symbols are a new primitive type.
Optional name parameter used in debugging - but is not part of identity.
Symbols are unique (like gensym), but not private
since they are exposed via reflection features like Object.getOwnPropertySymbols.
Limited support requires the Babel polyfill.
Due to language limitations, some features can't be transpiled or polyfilled.
See core.js's caveats section for more details.
In ES2015, built-ins like Array, Date and DOM Elements can be subclassed.
Built-in subclassability should be evaluated on a case-by-case basis as classes
such as HTMLElement can be subclassed
while many such as Date, Array and Error cannot be due to ES5 engine limitations.
Many new library additions, including core Math libraries, Array conversion helpers, and Object.assign for copying.
// 为啥下面3个运行报错???Excuse Me??? // iterator [0, "a"], [1,"b"], [2,"c"] ["a", "b", "c"].entries() // iterator 0, 1, 2 ["a", "b", "c"].keys() // iterator "a", "b", "c" ["a", "b", "c"].values() // 什么鬼??? Object.assign(Point, { origin: new Point(0,0) })Most of these APIs are supported by the Babel polyfill.
However, certain features are omitted for various reasons
(e.g. String.prototype.normalize needs a lot of additional code to support).
You can find more polyfills here.
Two new numeric literal forms are added for binary (b) and octal (o).
0b1000011 === 67 // true 0o103 === 67 // trueBabel is only able to transform 0o767 and not Number("0o767").
Full reflection API exposing the runtime-level meta-operations on objects.
This is effectively the inverse of the Proxy API,
and allows making calls corresponding to the same meta-operations as the proxy traps.
Especially useful for implementing proxies.
In order to use the Reflect API you must include the Babel polyfill.
Promises are a library for asynchronous programming.
Promises are a first class representation of a value that may be made available in the future.
Promises are used in many existing JavaScript libraries.
In order to support Promises you must include the Babel polyfill.
Calls in tail-position are guaranteed to not grow the stack unboundedly.
Makes recursive algorithms safe in the face of unbounded inputs.
function factorial(n, acc = 1) { "use strict"; if (n <= 1) return acc; return factorial(n - 1, n * acc); } // Stack overflow in most implementations today, // but safe on arbitrary inputs in ES2015 factorial(100000)Only explicit self referencing tail recursion was supported due to the complexity
and performance impact of supporting tail calls globally.
Removed due to other bugs and will be re-implemented.
This is left as implementation-defined within the ECMAScript 2015 specification.
The eventual standard will be in WHATWG's Loader specification, but that is currently a work in progress.
What is below is from a previous ES2015 draft.
Module loaders support:
Dynamic loadingState isolationGlobal namespace isolationCompilation hooksNested virtualizationThe default module loader can be configured,
and new loaders can be constructed to evaluated and load code in isolated or constrained contexts.
// Dynamic loading – ‘System’ is default loader// 1. 先requirevar System = require('systemjs')// 2. 配置System.config({ transpiler: './modules/es6_02_math.js' })// 3. 使用 (为啥没有输出 也没报错???Excuse Me???) System.import("./modules/es6_02_math").then(function(mathObj) { // 这个方法都没有进来??? alert("2π = " + mathObj.sum(mathObj.PI, mathObj.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 finalizedSince Babel defaults to using common.js modules,
it does not include the polyfill for the module loader API. Get it here.
https://github.com/ModuleLoader/es-module-loader
安装命令:
npm install es-module-loader --save-devIn order to use this, you'll need to tell Babel to use the system module formatter.
Also be sure to check out System.js
https://github.com/systemjs/systemjs
安装:
npm install systemjs --save
使用:
未完待续,下一章节,つづく
