1.1 ES6与ES2015ES6于2015年6月正式发布,其目标是使JS原因呢可用于编写大型的应用程序,成为企业级的开发语言。这篇文章主要介绍:
- ECMAScript的版本历史
- 使用babel对ES6代码进行转码
- 配合gulp搭建ES6开发环境
- ES6最常用的特性
标准的制定者计划,以后每年发布一次标准,使用年份作为版本号。ES6是在2015年发布的,所以又称为ES2015。但ES6其实多用于泛指ES5.1版本后的下一代JS标准,它涵盖在ES2015版本上稍作改动的ES2016。
1.2 ECMAScript与Javascript1996年11月,javascript的创造者网景公司将JS提交给国际化标准组织ECMA(European computer manufactures association,欧洲计算机制造联合会),希望这种语言能够成为国际标准。次年,ECMA发布了规定浏览器脚本语言的标准,即ECMAScript。该标准一开始就是针对JS语言制定的,之所以不使用Javascript这个名号,一是因为商标使用权的冲突,二则是想体现这门语言的制定者是ECMA而并非网景,这样有利于这门语言的开放和中立。
因此,可以这么说,ECMAScript是标准与规格,Javascript是对它的实现。此外,像Flash的ActionScript也遵循ECMAScript的规范,所以其基本语法看起来和javascript几乎一模一样。二者的主要区别则在于对页面元素的操作。使用JS可以轻松的对页面的元素进行操作,与浏览器进行交互,所以很多人又把javascript看成是ECMAScript+DOM(文档对象模型)+BOM(浏览器对象模型)的组合。
1.3 ECMAScript的历史- 1997年 ECMAScript 1.0 诞生
- 1999年12月 ECMAScript 3.0诞生,它 是一个巨大的成功,在业界得到了广泛的支持,它奠定了JS的基本语法,被其后版本完全继承。直到今天,我们一开始学习JS,其实就是在学3.0版的语法。
- 2000年的ECMAScript4.0是当下ES6的前身,但由于这个版本太过激烈,对ES3做了彻底升级,所以暂时被“和谐”了。
- 2009年12月,ECMAScript5.0版正式发布。ECMA专家组预计ECMAScript的第五个版本会在2013年中期到2018年作为主流的开发标准。2011年6月,ES5.1版发布,并且成为ISO国际标准。
- 2013年,ES6草案冻结,不再添加新的功能,新的功能将被放到ES7中;2015年6月,ES6正式通过,成为国际标准。
ES6强大的语法能够大大的加快我们的开发效率,但缺点在于老旧的环境对它的支持并不理想。我们可以使用转码技术将ES6代码转为被浏览器普遍支持的ES5代码,以保证浏览器的支持。Babel是当下最流行的转码器。
babel的名字取自“巴别塔”,据《圣经·旧约·创世记》第11章记载,是当时人类联合起来兴建,希望能通往天堂的高塔。为了阻止人类的计划,上帝让人类说不同的语言,使人类相互之间不能沟通,计划因此失败,人类自此各散东西,向世界各地迁移。
babel命令行工具
babel的命令行通过下面代码来安装
npm install babel-cli -g
npm install babel-preset-es2015 --save
然后再根目录创建名为.babelrc的配置文件。
{
"presets" : ["es2015"]
}
babel提供下面几种处理ES6代码的方式:
babel-node运行ES6代码
以REPL的方式直接运行ES6代码
babel-node
> var a = 10;console.log((a=>a*a)(a));
> 100
也可以直接运行ES6脚本。比如现在我们有两个ES6模块m1.js和m2.js,m1.js的内容如下:
import myInfo from './m2.js';
myInfo();
m2.js的内容为:
export default function () {
console.log('default')
};
运行
babel-node m1.js
输出:default。可见两个ES6文件都被正确的解析执行了。
Babel转换ES6代码
使用babel命令可以直接把ES6代码转化成ES5代码,但默认只是把转换后的代码输出到控制台,我们可以加上-o命令将转换后的代码重定向至文件。
babel foo.js -o bar.js
-d参数可以转换整个目录,注意资源目录和构建目录的顺序
babel -d build-dir sourse-dir
如果希望生成sourse-map,需要加上-s参数
babel foo.js -o bar.js -s
Babel在浏览器环境
首先在浏览器引入browser.js,然后在type="text/babel"的script元素中编写你的代码就可以了。可以使用下面的命令从npm上获取browser.js
npm install babel-core@5
文件在node_modules/babel-core子目录下。因为从babel6.0开始,不再直接提供浏览器的版本,所以我们通过安装第5个版本获取。
显然,这种做法对浏览器性能会有很坏的影响,而且本质上讲,这没有什么用。在开发时,最新版本的chrome可以实现大部分的ES6特性(除了模块的特性),在上线时,则可以使用已经经过转码的版本。
Babel在Nodejs环境
首先需要安装核心模块
npm install babel-core
npm install babel-preset-es2015 --save
然后再根目录创建名为.babelrc的配置文件。
{
"presets" : ["es2015"]
}
然后在应用的脚本入口(比如express的app.js)加上如下语句:
require("babel-core/register")
这样,后面所有通过require命令加载后缀名为.es6.js.jsx.es的脚本,都会通过babel先转码,再加载。
Babel不会转换Iterator、Generator、Set、Map等全局对象以及一些定义在全局对象上的方法,如果用到了这些功能,你的环境却不支持,就需要安装使用babel-polyfill模块。
npm install babel-polyfill --save
然后在所有脚本头部加上
require('babel-polyfill');
还可以使用babel-core模块以编码的形式进行转码,这可能会调用到nodejs的文件系统。我们一般使用gulp等构建工具取完成这个功能。
1.5 使用gulp搭建ES6环境开发中,我们常常配合gulp来搭建ES6开发环境。
下载依赖模块
"devDependencies": {
"babel-preset-es2015": "^6.24.0",
"gulp": "^3.9.1",
"gulp-babel": "^6.1.2",
"gulp-plumber": "^1.1.0",
"gulp-rename": "^1.2.2",
"gulp-sequence": "^0.4.6",
"gulp-watch": "^4.3.11"
}
需要babel-preset-es2015和gulp-babel转换ES6代码为ES5。
gulp-plumber的作用是在出现错误时重新启动gulp(gulp的设计使得gulp非常容易由于你想不到的原因挂掉,比如你使用let重复命名了变量)。
gulp-rename重命名产生的ES5文件,在后面加上“-es5”后缀。
gulp-watch用来检测文件变化,与gulp.watch()不同,gulp-watch可以监听文件的增加与删除。gulp-sequence与gulp-watch联合使用,它的作用是顺序触发一些任务。当watch监听到文件变化时(改变或增加),可以使用它触发任务。
配置文件
glupfile.js如下所示:
"use strict";
let gulp = require('gulp');
let babel = require("gulp-babel");
let rename = require("gulp-rename");
let plumber = require("gulp-plumber");
let watch = require("gulp-watch");
let gulpSequence = require("gulp-sequence");
let del = require('del');
gulp.task("es6", function () {
return gulp.src(['./project/**/*.js', '!./project/**/*-es5.js'])
.pipe(plumber())
.pipe(babel({
presets: ['es2015'],
compact: false
}))
.pipe(rename({
suffix: "-es5",
extname: ".js"
}))
.pipe(gulp.dest("./project"));
});
gulp.task('default', ['es6'], function () {
watch('./project/**/*.js', function () {
gulpSequence('es6')(function (err) {
if (err) console.log(err)
})
});
watch('./project/**/*.js', {events:['unlink']}, function (vinyl) {
let filename = vinyl.path.replace('.js','-es5.js');
del(filename)
});
});
这里我新加了一个功能,如果删除了es6文件,其生产的es5文件也对应被删除。如果不想这样,把上面这部分代码(del watch unlink那部分)注释掉就可以了。
还有一个比较坑的地方,就是在配置src路径的时候,如果不指定一个初始文件夹,比如./project,只写成./这样,就会报一些很奇怪的错误,回来有机会在解决。
这一节我们将会对接下来的教程中,我们将用到的取代ES5中的传统编码方法的高效ES6方法进行简要的介绍。
let与const
使用let代替var,let较var而言,支持块级作用域,不存在代码提升,同一作用域内不允许出现相同名称的变量。const与let特性基本相同,我们使用const声明常量,一旦声明必须立即赋值,并且不可更改。
箭头函数与函数默认值
使用箭头函数可以简化简单逻辑函数的编码,例如:
var foo = function(a){
a = a||1; // a的默认值为1
return a*a
}
可以用箭头函数+参数默认值表示为:
let foo = (a=1)=>a*a
//更完全的形式为
let foo = (a=1)=>{return a*a}
模板字符串
使用模板字符串可以轻松的在字符串中进行变量的替换。注意使用模板时,最外层为``号(反引号),变量使用${}包裹。
let name = 'Kyle';
let bar ='学生'+name+'正在学习ES6';
// 等价于
let foo = `学生${name}正在学习ES6`;
解构赋值
解构赋值可以帮助我们快速的把对象里的值转移到局部变量中,比如:
let {c, d} = {c:'c',d:'d',e:'e'};
console.log(c); // c
console.log(d); // d
let [d,b,c] = [1,2,3];
console.log(d); // 1
console.log(b); //2
console.log(c); //3
模块化
ES6提供了模块化的原生支持
// 引入模块
import {readFile, writeFile} from 'fs'
readFile('./a.txt', ()=>{
// do something
});
// 导出模块
export function foo(){
console.log('foo');
}
其它
ES6还提供了其它非常有用的语法与特性,比如:class作为传进对象的语法糖,promise提供异步调用的解决方案,Set,Map数据结构等等。在接下来的几天内我们将一点点深入学习。
热门评论
要写ES6一系列嘛?