ECMAScript 6.0(简称ES6)是 JavaScript 一个制定于2015年的新标准,它于2015年6月正式发布。javascript
它的目的是想让JavaScript成为一个企业级的开发语言,能够去开发大型的复杂应用。html
个人ES6学习心得将分为如下三个部分来阐述:java
1.ECMAScript 6.0简介node
2.ECMAScript 6.0新特性程序员
3.ECMAScript 6.0性能总结与我的体会es6
4.参考文献编程
1.ECMAScript 6.0简介数组
想要弄清楚ECMAScript 6.0,那么咱们要先弄清楚它是什么,它怎么来的。浏览器
(1)ECMAScript闭包
ECMA是“European Computer Manufactures Association”的缩写,中文称欧洲计算机制造联合会。这个组织的目标是评估,开发和承认电信和计算机标准。
1996年的时候,Javascript的创造公司将Javascript提交给ECMA,但愿这种语言可以成为国际标准。
次年,ECMA 发布262号标准文件(ECMA-262)的初版,规定了浏览器脚本语言Javascript的标准,并将这种语言称为 ECMAScript,这个版本就是1.0版。
因此咱们这里总结一下ECMAscript与Javascript之间的关系:
ECMAscript是Javascript的标准/规格
Javascript是ECMAscript的实现(另外的 ECMAScript 语言还有 Jscript 和 ActionScript)
可是咱们通常平常说的ECMAScript就是Javascript的意思,这两个词是能够互换的,不过仍是要清楚它们的区别。
(2)ECMAScript 6.0(ES6) / ECMAScript 2015(ES2015)
2011年,ECMAScript 5.1版发布后,就开始制定6.0版了。所以,ES6 这个词的原意,就是指 ECMAScript 5.1版的下一个版本。
由于ECMA标准委员会会在每一年6月份更新并正式发布一次新的ECMAScript标准,做为当年的正式版本。
而后接下来的时间就是在这个版本的基础上面作改动,一直到下年的6月份。这样一来其实就不须要用版本号来区分了了,用年份标记便可。
ES6 的第一个版本,就这样在2015年6月发布了,正式名称就是《ECMAScript 2015标准》(简称 ES2015)。
2016年6月,小幅修订的《ECMAScript 2016标准》(简称 ES2016)如期发布,这个版本能够看做是 ES6.1 版,由于二者的差别很是小(只新增了数组实例的includes
方法和指数运算符),基本上是同一个标准。根据计划,2017年6月发布 ES2017 标准。
所以,ECMAScript6.0既是一个版本名称,也是一个类别。版本名称是指5.1版之后的 ECMAScript 的下一代标准,类别是指它涵盖了ES201五、ES201六、ES2017等等。
而ES2015 则是正式名称,特指该年发布的正式版本的语言标准。
2.ECMAScript 6.0新特性
以前刚开始接触Javascript的时候ES6还没推出,用的仍是ES5的标准,那么新推出的ES6有哪些新特性呢?
下文我将总结一些在ES6的学习中接触到的一些比较经常使用的语法特性,具体有如下几项:
(1)let, const
(2)class, extends, super
(3)arrow function
(4)template string
(5)destructuring
(6)default, reat
--------------------华丽丽的分界线---------------------
(1)let, const
let, const的做用与var相似,都是用于声明变量的,可是它们减小了var在做用域以及赋值方面的缺陷,下面咱们来看一下。
①var在做用域方面的缺陷
var name = 'zach' while (true) { var name = 'obama' console.log(name) //obama break } console.log(name) //obama
使用var
两次输出都是obama,这是由于ES5只有全局做用域和函数做用域,没有块级做用域,这带来不少不合理的场景。第一种场景就是你如今看到的内层变量覆盖外层变量。而let
则实际上为JavaScript新增了块级做用域。用它所声明的变量,只在let
命令所在的代码块内有效。
let name = 'zach' while (true) { let name = 'obama' console.log(name) //obama break } console.log(name) //zach
另一个var
带来的不合理场景就是用来计数的循环变量泄露为全局变量,看下面的例子:
var a = []; for (var i = 0; i < 10; i++) { a[i] = function () { console.log(i); }; } a[6](); // 10
上面代码中,变量i是var声明的,在全局范围内都有效,因此全局只有一个变量i。每一次循环,变量i的值都会发生改变,而循环内被赋给数组a的function在运行时,会经过闭包读到这同一个变量i,致使最后输出的是最后一轮的i的值,也就是10。而使用let则不会出现这个问题。
var a = []; for (let i = 0; i < 10; i++) { a[i] = function () { console.log(i); }; } a[6](); // 6
上面代码中,变量i是let声明的,当前的i只在本轮循环有效,因此每一次循环的i其实都是一个新的变量,因此最后输出的是6。你可能会问,若是每一轮循环的变量i都是从新声明的,那它怎么知道上一轮循环的值,从而计算出本轮循环的值?这是由于 JavaScript 引擎内部会记住上一轮循环的值,初始化本轮的变量i时,就在上一轮循环的基础上进行计算。
另外,for循环还有一个特别之处,就是循环语句部分是一个父做用域,而循环体内部是一个单独的子做用域。
for (let i = 0; i < 3; i++) { let i = 'abc'; console.log(i); } // abc // abc // abc
上面代码输出了3次abc,这代表函数内部的变量i和外部的变量i是分离的。
②var在赋值方面的缺陷
从上面的例子咱们能够看出,var的赋值是能够很轻易地被改变的
var name = 'zach' while (true) { var name = 'obama' console.log(name) //obama break } console.log(name) //obama
这就带来了一个问题,一些程序中比较重要的变量很容易就会被他人,特别是你绝不知情的队友改变了,这就给咱们大型程序的开发带来了麻烦。
固然上文仅仅是我设想的一个场景,咱们的程序中更多的时候是须要一些约定俗成,值不变的常量,好比说pi。
在ES6中,咱们添加了const特性来声明常量。一旦声明,常量的值就不能改变。
const PI = Math.PI PI = 23 //Module build failed: SyntaxError: /es6/app.js: "PI" is read-only
当咱们尝试去改变用const声明的常量时,浏览器就会报错。
const有一个很好的应用场景,就是当咱们引用第三方库的时声明的变量,用const来声明能够避免将来不当心重命名而致使出现bug:
const monent = require('moment')
(2)class, extends, super
ES6还有一大特色就是它跟咱们所熟知的入门级语言C、C++更像了,由于它引入了class(类)这个概念。
在ES5的年代,js是没有特定的class这个概念的,因此咱们以前通常经过构造函数定义并生成新对象,以下图:
function Point(x, y) { this.x = x; this.y = y; } Point.prototype.toString = function () { return '(' + this.x + ', ' + this.y + ')'; }; var p = new Point(1, 2);
可是上面这种写法跟传统的面向对象语言(好比C++和Java)差别很大,很容易让刚接触的程序员感到困惑。
ES6提供了更接近传统的面向对象语言的写法,引入了Class(类)这个概念。
在ES6中,经过class
关键字,咱们能够定义类。
但其实ES6的class
仅仅是个名字/写法而已,由于它的绝大部分功能,ES5均可以作到。
不过新的class
写法让对象原型的写法更加清晰、更像面向对象编程的语法,这样就能够更接近企业级的开发语言。
上面的代码用ES6的“类”改写,就是下面这样。
//定义类 class Point { constructor(x, y) { this.x = x; this.y = y; } toString() { return '(' + this.x + ', ' + this.y + ')'; } }
上面代码首先用class
定义了一个“类”,能够看到里面有一个constructor
方法,这就是构造方法,而this
关键字则表明实例对象。简单地说,constructor
内定义的方法和属性是实例对象本身的,而constructor
外定义的方法和属性则是全部实例对象能够共享的。
Point
类除了构造方法,还定义了一个toString
方法。注意,定义“类”的方法的时候,前面不须要加上function
这个关键字,直接把函数定义放进去了就能够了。另外,方法之间不须要逗号分隔,加了会报错。
ES6的类,彻底能够看做构造函数的另外一种写法。
class Point { // ... } typeof Point // "function" Point === Point.prototype.constructor // true
Class之间能够经过extends
关键字实现继承,这比ES5的经过修改原型链实现继承,要清晰和方便不少。下面定义了一个Cat类,该类经过extends
关键字,继承了Animal类的全部属性和方法。
class Animal { constructor(){ this.type = 'animal' } says(say){ console.log(this.type + ' says ' + say) } } let animal = new Animal() animal.says('hello') //animal says hello class Cat extends Animal { constructor(){ super() this.type = 'cat' } } let cat = new Cat() cat.says('hello') //cat says hello
super
关键字,它指代父类的实例(即父类的this对象)。子类必须在constructor
方法中调用super
方法,不然新建实例时会报错。这是由于子类没有本身的this
对象,而是继承父类的this
对象,而后对其进行加工。若是不调用super
方法,子类就得不到this
对象。
ES6的继承机制,实质是先创造父类的实例对象this(因此必须先调用super方法),而后再用子类的构造函数修改this。
(3)arrow function
ES6带来的还有一个新特性,就是简洁。
arrow function应该是ES6最最经常使用的一个新特性了,用它来写function比原来的写法要简洁清晰不少:
function(i){ return i + 1; } //ES5 (i) => i + 1 //ES6
若是function有多行内容,则须要用{}将其括起来:
function(x, y) { x++; y--; return x + y; }//ES5 (x, y) => {x++; y--; return x+y}//ES6
另外ES5在使用this的时候也须要当心混淆:
class Animal { constructor(){ this.type = 'animal' } says(say){ setTimeout(function(){ console.log(this.type + ' says ' + say) }, 1000) } } var animal = new Animal() animal.says('hi') //undefined says hi
运行上面的代码会报错,这是由于setTimeout
中的this
指向的是全局对象。
通常用ES5的解决方法有传递this或者bind(this)这些, 但如今咱们有了箭头函数,就不须要这么麻烦了:
class Animal { constructor(){ this.type = 'animal' } says(say){ setTimeout( () => { console.log(this.type + ' says ' + say) }, 1000) } } var animal = new Animal() animal.says('hi') //animal says hi
当咱们使用箭头函数时,函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。
并非由于箭头函数内部有绑定this的机制,实际缘由是箭头函数根本没有本身的this,它的this是继承外面的,所以内部的this就是外层代码块的this。
可是在这里咱们要说的是,arrow function也并非一劳永逸的,特别是在你并不知道this指向哪的时候,你须要慎用arrow function。
由于arrow function是 Lexical scoping(词法做用域),this指向定义Arrow Function时外围, 而不是运行时的对象。
词法做用域: 变量的做用域是在定义时决定而不是执行时决定,也就是说词法做用域取决于源码,经过静态分析就能肯定,所以词法做用域也叫作静态做用域。
下面咱们将根据文章:Do ES6 Arrow Functions Really Solve “this” In JavaScript? 来分析。
以下代码:
// run this in node v4 to see the "expected" behavior this.test = "attached to the module"; var foo = { test: "attached to an object" }; // a method to create methods foo.method = function(name, cb){ this[name] = cb; }; // use an arrow function and get // lexical analysis of "this" foo.method("bar", () => { // not what you expected, maybe? console.log(this.test); }); foo.bar();
输出为:“attached to the module”而不是“attached to an object”
由于
就像咱们所说的,arrow function是 Lexical scoping,由于在foo.method("bar", () => {的外围并无包含着它的代码,因此,foo.bar()中的this.test值将永远是“attached to the module”。
(4)template string
这个新特性能够帮助咱们插入大段的html内容到文档中去。传统的写法通常比较麻烦,因此以前咱们一般会引用一些模板工具库,好比mustache等等。代码以下:
$("#result").append( "There are <b>" + basket.count + "</b> " + "items in your basket, " + "<em>" + basket.onSale + "</em> are on sale!" );
咱们要用一堆的'+'号来链接文本与变量,而使用ES6的新特性模板字符串``后,咱们能够直接这么来写:
$("#result").append(` There are <b>${basket.count}</b> items in your basket, <em>${basket.onSale}</em> are on sale! `);
在ES6中,咱们用`来标识开始和结尾,用${}来引用变量,并且全部的空格和缩进都会被保留在输出之中。
(5)destructuring
ES6容许按照必定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring)。
当使用ES5的时候,咱们通常是这么写的:
let cat = 'ken' let dog = 'lili' let zoo = {cat: cat, dog: dog} console.log(zoo) //Object {cat: "ken", dog: "lili"}
用ES6彻底能够像下面这么写:
let cat = 'ken' let dog = 'lili' let zoo = {cat, dog} console.log(zoo) //Object {cat: "ken", dog: "lili"}
反过来能够这么写:
let dog = {type: 'animal', many: 2} let { type, many} = dog console.log(type, many) //animal 2
(6)default, reat
default很简单,意思就是默认值。你们能够看下面的例子,调用animal()
方法时忘了传参数,传统的作法就是加上这一句type = type || 'cat'
来指定默认值。
function animal(type){ type = type || 'cat' console.log(type) } animal()
若是用ES6咱们能够直接这么写:
function animal(type = 'cat'){ console.log(type) } animal()
最后一个rest语法也很简单,直接看例子:
function animals(...types){ console.log(types) } animals('cat', 'dog', 'fish') //["cat", "dog", "fish"]
而若是不用ES6的话,咱们则得使用ES5的arguments
。
3.ECMAScript 6.0性能总结与我的体会
整体来看,ES6正在朝着更简洁、更友好、可读性更强、更模块化的方向发展,这些特性都能支持其成为一个企业级的开发语言,能够去开发大型的复杂应用。
本文章从ES6的来历,讲到ES6的一些新特性。但以上仅仅列出了ES6中一些比较经常使用的新特性,并且分析的并不够深刻,因此咱们仍是须要再去深一步学习和摸索的。“实践是检验真理的惟一方法”,之后在实战项目中遇到的问题我会再来写博客分析的。
4.参考文献
http://www.jianshu.com/p/ebfeb687eb70
http://es6.ruanyifeng.com/#docs/function
http://cnodejs.org/topic/57266e375a26c4a841ecbf40
https://derickbailey.com/2015/09/28/do-es6-arrow-functions-really-solve-this-in-javascript/
http://www.cnblogs.com/jiangyi666/p/5998914.html
http://blog.csdn.net/pengju_guo/article/details/7292080