乐趣区

关于ecmascript:ECMAScript-6-简介

ECMAScript 6 简介
ECMAScript 6.0(以下简称 ES6)是 JavaScript 语言的下一代规范,曾经在 2015 年 6 月正式公布了。它的指标,是使得 JavaScript 语言能够用来编写简单的大型应用程序,成为企业级开发语言。

ECMAScript 和 JavaScript 的关系

一个常见的问题是,ECMAScript 和 JavaScript 到底是什么关系?

要讲清楚这个问题,须要回顾历史。1996 年 11 月,JavaScript 的创造者 Netscape 公司,决定将 JavaScript 提交给标准化组织 ECMA,心愿这种语言可能成为国际标准。次年,ECMA 公布 262 号标准文件(ECMA-262)的第一版,规定了浏览器脚本语言的规范,并将这种语言称为 ECMAScript,这个版本就是 1.0 版。

该规范从一开始就是针对 JavaScript 语言制订的,然而之所以不叫 JavaScript,有两个起因。一是商标,Java 是 Sun 公司的商标,依据受权协定,只有 Netscape 公司能够非法地应用 JavaScript 这个名字,且 JavaScript 自身也曾经被 Netscape 公司注册为商标。二是想体现这门语言的制定者是 ECMA,不是 Netscape,这样有利于保障这门语言的开放性和中立性。

因而,ECMAScript 和 JavaScript 的关系是,前者是后者的规格,后者是前者的一种实现(另外的 ECMAScript 方言还有 JScript 和 ActionScript)。日常场合,这两个词是能够调换的。

ES6 与 ECMAScript 2015 的关系

ECMAScript 2015(简称 ES2015)这个词,也是常常能够看到的。它与 ES6 是什么关系呢?

2011 年,ECMAScript 5.1 版公布后,就开始制订 6.0 版了。因而,ES6 这个词的原意,就是指 JavaScript 语言的下一个版本。

然而,因为这个版本引入的语法性能太多,而且制订过程当中,还有很多组织和集体一直提交新性能。事件很快就变得分明了,不可能在一个版本外面包含所有将要引入的性能。惯例的做法是先公布 6.0 版,过一段时间再发 6.1 版,而后是 6.2 版、6.3 版等等。

然而,规范的制定者不想这样做。他们想让规范的降级成为惯例流程:任何人在任何时候,都能够向规范委员会提交新语法的提案,而后规范委员会每个月开一次会,评估这些提案是否能够承受,须要哪些改良。如果通过屡次会议当前,一个提案足够成熟了,就能够正式进入规范了。这就是说,规范的版本升级成为了一个一直滚动的流程,每个月都会有变动。

规范委员会最终决定,规范在每年的 6 月份正式公布一次,作为当年的正式版本。接下来的工夫,就在这个版本的根底上做改变,直到下一年的 6 月份,草案就天然变成了新一年的版本。这样一来,就不须要以前的版本号了,只有用年份标记就能够了。

ES6 的第一个版本,就这样在 2015 年 6 月公布了,正式名称就是《ECMAScript 2015 规范》(简称 ES2015)。2016 年 6 月,小幅订正的《ECMAScript 2016 规范》(简称 ES2016)如期公布,这个版本能够看作是 ES6.1 版,因为两者的差别十分小(只新增了数组实例的 includes 办法和指数运算符),基本上是同一个规范。依据打算,2017 年 6 月公布 ES2017 规范。

因而,ES6 既是一个历史名词,也是一个泛指,含意是 5.1 版当前的 JavaScript 的下一代规范,涵盖了 ES2015、ES2016、ES2017 等等,而 ES2015 则是正式名称,特指该年公布的正式版本的语言规范。本书中提到 ES6 的中央,个别是指 ES2015 规范,但有时也是泛指“下一代 JavaScript 语言”。

语法提案的批准流程

任何人都能够向规范委员会(又称 TC39 委员会)提案,要求批改语言规范。

一种新的语法从提案到变成正式规范,须要经验五个阶段。每个阶段的变动都须要由 TC39 委员会批准。

Stage 0 – Strawman(展现阶段)
Stage 1 – Proposal(征求意见阶段)
Stage 2 – Draft(草案阶段)
Stage 3 – Candidate(候选人阶段)
Stage 4 – Finished(定案阶段)
一个提案只有能进入 Stage 2,就差不多必定会包含在当前的正式规范外面。ECMAScript 以后的所有提案,能够在 TC39 的官方网站 GitHub.com/tc39/ecma262 (opens new window) 查看。

本书的写作指标之一,是跟踪 ECMAScript 语言的最新进展,介绍 5.1 版本当前所有的新语法。对于那些明确或很有心愿,将要列入规范的新语法,都将予以介绍。

ECMAScript 的历史

ES6 从开始制订到最初公布,整整用了 15 年。

后面提到,ECMAScript 1.0 是 1997 年公布的,接下来的两年,间断公布了 ECMAScript 2.0(1998 年 6 月)和 ECMAScript 3.0(1999 年 12 月)。3.0 版是一个微小的胜利,在业界失去广泛支持,成为通行规范,奠定了 JavaScript 语言的根本语法,当前的版本齐全继承。直到明天,初学者一开始学习 JavaScript,其实就是在学 3.0 版的语法。

2000 年,ECMAScript 4.0 开始酝酿。这个版本最初没有通过,然而它的大部分内容被 ES6 继承了。因而,ES6 制订的终点其实是 2000 年。

为什么 ES4 没有通过呢?因为这个版本太激进了,对 ES3 做了彻底降级,导致规范委员会的一些成员不违心承受。ECMA 的第 39 号技术专家委员会(Technical Committee 39,简称 TC39)负责制订 ECMAScript 规范,成员包含 Microsoft、Mozilla、Google 等大公司。

2007 年 10 月,ECMAScript 4.0 版草案公布,原本预计次年 8 月公布正式版本。然而,各方对于是否通过这个规范,产生了重大一致。以 Yahoo、Microsoft、Google 为首的大公司,拥护 JavaScript 的大幅降级,主张小幅改变;以 JavaScript 创造者 Brendan Eich 为首的 Mozilla 公司,则保持以后的草案。

2008 年 7 月,因为对于下一个版本应该包含哪些性能,各方一致太大,争执过于强烈,ECMA 散会决定,停止 ECMAScript 4.0 的开发,将其中波及现有性能改善的一小部分,公布为 ECMAScript 3.1,而将其余激进的构想扩大范围,放入当前的版本,因为会议的氛围,该版本的我的项目代号起名为 Harmony(谐和)。会后不久,ECMAScript 3.1 就改名为 ECMAScript 5。

2009 年 12 月,ECMAScript 5.0 版正式公布。Harmony 我的项目则一分为二,一些较为可行的构想定名为 JavaScript.next 持续开发,起初演变成 ECMAScript 6;一些不是很成熟的构想,则被视为 JavaScript.next.next,在更远的未来再思考推出。TC39 委员会的总体思考是,ES5 与 ES3 根本放弃兼容,较大的语法修改和新性能退出,将由 JavaScript.next 实现。过后,JavaScript.next 指的是 ES6,第六版公布当前,就指 ES7。TC39 的判断是,ES5 会在 2013 年的年中成为 JavaScript 开发的支流规范,并在尔后五年中始终放弃这个地位。

2011 年 6 月,ECMAScript 5.1 版公布,并且成为 ISO 国际标准(ISO/IEC 16262:2011)。

2013 年 3 月,ECMAScript 6 草案解冻,不再增加新性能。新的性能构想将被放到 ECMAScript 7。

2013 年 12 月,ECMAScript 6 草案公布。而后是 12 个月的探讨期,听取各方反馈。

2015 年 6 月,ECMAScript 6 正式通过,成为国际标准。从 2000 年算起,这时曾经过来了 15 年。

目前,各大浏览器对 ES6 的反对能够查看 kangax.github.io/compat-table/es6/ (opens new window)。

Node.js 是 JavaScript 的服务器运行环境(runtime)。它对 ES6 的反对度更高。除了那些默认关上的性能,还有一些语法性能曾经实现了,然而默认没有关上。应用上面的命令,能够查看 Node.js 默认没有关上的 ES6 实验性语法。

// Linux & Mac
$ node --v8-options | grep harmony

// Windows
$ node --v8-options | findstr harmony

Babel 转码器

Babel (opens new window) 是一个宽泛应用的 ES6 转码器,能够将 ES6 代码转为 ES5 代码,从而在老版本的浏览器执行。这意味着,你能够用 ES6 的形式编写程序,又不必放心现有环境是否反对。上面是一个例子。

// 转码前

input.map((item) => item + 1);

// 转码后

input.map(function (item) {return item + 1;});

下面的原始代码用了箭头函数,Babel 将其转为一般函数,就能在不反对箭头函数的 JavaScript 环境执行了。

上面的命令在我的项目目录中,装置 Babel。

$ npm install --save-dev @babel/core

配置文件.babelrc

Babel 的配置文件是.babelrc,寄存在我的项目的根目录下。应用 Babel 的第一步,就是配置这个文件。

该文件用来设置转码规定和插件,根本格局如下。

{"presets": [],
  "plugins": []}

presets 字段设定转码规定,官网提供以下的规定集,你能够依据须要装置。

最新转码规定

$ npm install –save-dev @babel/preset-env

react 转码规定

$ npm install --save-dev @babel/preset-react

而后,将这些规定退出.babelrc。

{
   "presets": [
     "@babel/env",
     "@babel/preset-react"
   ],
   "plugins": []}

留神,以下所有 Babel 工具和模块的应用,都必须先写好.babelrc。

命令行转码

Babel 提供命令行工具 @babel/cli,用于命令行转码。

它的装置命令如下。

$ npm install --save-dev @babel/cli

根本用法如下。

转码后果输入到规范输入

$ npx babel example.js

转码后果写入一个文件

–out-file 或 -o 参数指定输入文件

$ npx babel example.js --out-file compiled.js

或者

$ npx babel example.js -o compiled.js

整个目录转码

–out-dir 或 -d 参数指定输入目录

$ npx babel src --out-dir lib

或者

$ npx babel src -d lib

-s 参数生成 source map 文件

$ npx babel src -d lib -s

babel-node

@babel/node 模块的 babel-node 命令,提供一个反对 ES6 的 REPL 环境。它反对 Node 的 REPL 环境的所有性能,而且能够间接运行 ES6 代码。

首先,装置这个模块。

$ npm install --save-dev @babel/node

而后,执行 babel-node 就进入 REPL 环境。

$ npx babel-node
> (x => x * 2)(1)
2

babel-node 命令能够间接运行 ES6 脚本。将下面的代码放入脚本文件 es6.js,而后间接运行。

# es6.js 的代码
# console.log((x => x * 2)(1));
$ npx babel-node es6.js
2

@babel/register 模块

@babel/register 模块改写 require 命令,为它加上一个钩子。尔后,每当应用 require 加载.js、.jsx、.es 和.es6 后缀名的文件,就会先用 Babel 进行转码。

$ npm install --save-dev @babel/register

应用时,必须首先加载 @babel/register。

// index.js
require('@babel/register');
require('./es6.js');

而后,就不须要手动对 index.js 转码了。

$ node index.js
2

须要留神的是,@babel/register 只会对 require 命令加载的文件转码,而不会对以后文件转码。另外,因为它是实时转码,所以只适宜在开发环境应用。

polyfill

Babel 默认只转换新的 JavaScript 句法(syntax),而不转换新的 API,比方 Iterator、Generator、Set、Map、Proxy、Reflect、Symbol、Promise 等全局对象,以及一些定义在全局对象上的办法(比方 Object.assign)都不会转码。

举例来说,ES6 在 Array 对象上新增了 Array.from 办法。Babel 就不会转码这个办法。如果想让这个办法运行,能够应用 core-js 和 regenerator-runtime(后者提供 generator 函数的转码),为以后环境提供一个垫片。

装置命令如下。

$ npm install --save-dev core-js regenerator-runtime

而后,在脚本头部,退出如下两行代码。

import 'core-js';
import 'regenerator-runtime/runtime';
// 或者
require('core-js');
require('regenerator-runtime/runtime);

Babel 默认不转码的 API 十分多,具体清单能够查看 babel-plugin-transform-runtime 模块的 definitions.js (opens new window) 文件。

浏览器环境

Babel 也能够用于浏览器环境,应用 @babel/standalone (opens new window) 模块提供的浏览器版本,将其插入网页。

<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<script type="text/babel">
  // Your ES6 code
</script>

留神,网页实时将 ES6 代码转为 ES5,对性能会有影响。生产环境须要加载曾经转码实现的脚本。

Babel 提供一个 REPL 在线编译器 (opens new window),能够在线将 ES6 代码转为 ES5 代码。转换后的代码,能够间接作为 ES5 代码插入网页运行。

退出移动版