ES6的十大特性具体包括哪些,你能详细介绍一下吗?
- 内容介绍
- 文章标签
- 相关推荐
本文共计3956个文字,预计阅读时间需要16分钟。
ES6(ECMAScript 2015)的推出,为前端开发人员带来了诸多惊喜。它包含了许多酷炫的新特性,可简化实现复杂操作,提高开发效率。以下是对ES6的简要介绍:
ES6(ECMAScript2015)的出现,无疑给前端开发人员带来了新的惊喜,它包含了一些很棒的新特性,可以更加方便的实现很多复杂的操作,提高开发人员的效率。
本文主要针对ES6做一个简要介绍。
也许你还不知道ES6是什么, 实际上, 它是一种新的javascript规范。在这个大家都很忙碌的时代,如果你想对ES6有一个快速的了解,那么请继续往下读,去了解当今最流行的编程语言JavaScript最新一代的十大特性。
以下是ES6排名前十的最佳特性列表(排名不分先后):
1.Block-Scoped Constructs Let and Const(块作用域构造Let and Const)
2.Arrow Functions (箭头函数)in ES6
3.Default Parameters(默认参数) in ES6
4.Template Literals (模板文本)in ES6
5.Multi-line Strings (多行字符串)in ES6
6.Destructuring Assignment (解构赋值)in ES6
7.Enhanced Object Literals (增强的对象文本)in ES6
8.Promises in ES6
9.Classes(类) in ES6
10.Modules(模块) in ES6
首先回顾一下JavaScript的历史,不清楚历史的人,很难理解JavaScript为什么会这样发展。下面就是一个简单的JavaScript发展时间轴:
1、1995:JavaScript诞生,它的初始名叫LiveScript。
2、1997:ECMAScript标准确立。
3、1999:ES3出现,与此同时IE5风靡一时。
4、2000–2005: XMLHttpRequest又名AJAX, 在Outlook Web Access (2000)、Oddpost (2002),Gmail (2004)和Google Maps (2005)大受重用。
5、2009: ES5出现,(就是我们大多数人现在使用的)例如foreach,Object.keys,Object.create和JSON标准。
6、2015:ES6/ECMAScript2015出现。
历史回顾就先到此,现让我们进入正题。
1.Block-Scoped Constructs Let and Const(块作用域和构造let和const)
在ES6代码中,你可能已经看到那熟悉的身影let。在ES6里let并不是一个花俏的特性,它是更复杂的。Let是一种新的变量声明方式,它允许你把变量作用域控制在块级里面。我们用大括号定义代码块,在ES5中,块级作用域起不了任何作用:
functioncalculateTotalAmount(vip){ varamount=0; if(vip){ varamount=1; } {//morecrazyblocks! varamount=100; { varamount=1000; } } returnamount; } console.log(calculateTotalAmount(true)); 结果将返回1000,这真是一个bug。在ES6中,我们用let限制块级作用域。而var是限制函数作用域。 functioncalculateTotalAmount(vip){ varamount=0;//probablyshouldalsobelet,butyoucanmixvarandlet if(vip){ letamount=1;//firstamountisstill0 } {//morecrazyblocks! letamount=100;//firstamountisstill0 { letamount=1000;//firstamountisstill0 } } returnamount; } console.log(calculateTotalAmount(true));
这个结果将会是0,因为块作用域中有了let。如果(amount=1).那么这个表达式将返回1。谈到const,就更加容易了;它就是一个常量,也是块级作用域就像let一样。下面是一个演示,这里有一堆常量,它们互不影响,因为它们属于不同的块级作用域:
functioncalculateTotalAmount(vip){ constamount=0; if(vip){ constamount=1; } {//morecrazyblocks! constamount=100; { constamount=1000; } } returnamount; } console.log(calculateTotalAmount(true));
在传统的var中,一个变量可以多次重复声明,如果代码很长的话,出现变量重复声明的错误是很难排查出来的,而let和const都不可以重复声明,从我个人看来,let 和const在大型的代码排错中起着至关重要的作用。
2.Arrow Functions in(箭头函数) ES6
这是我迫不及待想讲的一个特征,CoffeeScript 就是因为它丰富的箭头函数让很多开发者喜爱。在ES6中,也有了丰富的箭头函数。这些丰富的箭头是令人惊讶的因为它们将使许多操作变成现实,比如,
以前我们使用闭包,this总是预期之外地产生改变,而箭头函数的迷人之处在于,现在你的this可以按照你的预期使用了,身处箭头函数里面,this还是原来的this。
有了箭头函数在ES6中, 我们就不必用that = this或 self = this 或 _this = this 或.bind(this)。例如,下面的代码用ES5就不是很优雅:
var_this=this; $('.btn').click(function(event){ _this.sendData(); }) 在ES6中就不需要用_this=this: $('.btn').click((event)=>{ this.sendData(); })
不幸的是,ES6委员会决定,以前的function的传递方式也是一个很好的方案,所以它们仍然保留了以前的功能。
下面这是一个另外的例子,我们通过call传递文本给logUpperCase() 函数在ES5中:
varlogUpperCase=function(){ var_this=this; this.string=this.string.toUpperCase(); returnfunction(){ returnconsole.log(_this.string); } } logUpperCase.call({string:'ES6rocks'})();
而在ES6,我们并不需要用_this浪费时间:
varlogUpperCase=function(){ this.string=this.string.toUpperCase(); return()=>console.log(this.string); } logUpperCase.call({string:'ES6rocks'})();
请注意,只要你愿意,在ES6中=>可以混合和匹配老的函数一起使用。当在一行代码中用了箭头函数,它就变成了一个表达式。它将暗地里返回单个语句的结果。如果你超过了一行,将需要明确使用return。
这是用ES5代码创建一个消息数组:
varids=['5632953c4e345e145fdf2df8','563295464e345e145fdf2df9']; varmessages=ids.map(function(value){ return"IDis"+value;//explicitreturn });
用ES6是这样:
varids=['5632953c4e345e145fdf2df8','563295464e345e145fdf2df9']; varmessages=ids.map(value=>`IDis${value}`);//implicitreturn
请注意,这里用了字符串模板。
在箭头函数中,对于单个参数,括号()是可选的,但当你超过一个参数的时候你就需要他们。
在ES5代码有明确的返回功能:
varids=['5632953c4e345e145fdf2df8','563295464e345e145fdf2df9']; varmessages=ids.map(function(value,index,list){ return'IDof'+index+'elementis'+value+'';//explicitreturn });
在ES6中有更加严谨的版本,参数需要被包含在括号里并且它是隐式的返回:
varids=['5632953c4e345e145fdf2df8','563295464e345e145fdf2df9']; varmessages=ids.map((value,index,list)=>`IDof${index}elementis${value}`);//implicitreturn
3.Default Parameters(默认参数) in ES6
还记得我们以前不得不通过下面方式来定义默认参数:
varlink=function(height,color,url){ varheight=height||50; varcolor=color||'red'; varurl=url||'www.yzmcms.com'; ... }
一切工作都是正常的,直到参数值是0后,就有问题了,因为在JavaScript中,0表示fasly,它是默认被hard-coded的值,而不能变成参数本身的值。当然,如果你非要用0作为值,我们可以忽略这一缺陷并且使用逻辑OR就行了!但在ES6,我们可以直接把默认值放在函数申明里:
varlink=function(height=50,color='red',url='www.yzmcms.com'){ ... }
顺便说一句,这个语法跟PHP中是一样的!
4.Template Literals(模板对象) in ES6
在其它语言中,使用模板和插入值是在字符串里面输出变量的一种方式。因此,在ES5,我们可以这样组合一个字符串:
varname='Yournameis'+first+''+last+'.'; varurl='blog.yzmcms.com/api/messages/'+id;
幸运的是,在ES6中,我们可以使用新的语法$ {NAME},并把它放在反引号里:
varname=`Yournameis${first}${last}.`; varurl=`blog.yzmcms.com/api/messages/${id}`;
5.Multi-line Strings (多行字符串)in ES6
ES6的多行字符串是一个非常实用的功能。在ES5中,我们不得不使用以下方法来表示多行字符串:
varroadPoem='Thentooktheother,asjustasfair,nt' +'Andhavingperhapsthebetterclaimnt' +'Becauseitwasgrassyandwantedwear,nt' +'Thoughasforthatthepassingtherent' +'Hadwornthemreallyaboutthesame,nt'; varfourAgreements='Youhavetherighttobeyou.n Youcanonlybeyouwhenyoudoyourbest.';
然而在ES6中,仅仅用反引号就可以解决了:
varroadPoem=`Thentooktheother,asjustasfair, Andhavingperhapsthebetterclaim Becauseitwasgrassyandwantedwear, Thoughasforthatthepassingthere Hadwornthemreallyaboutthesame,`; varfourAgreements=`Youhavetherighttobeyou. Youcanonlybeyouwhenyoudoyourbest.`;
6.Destructuring Assignment (解构赋值)in ES6
解构可能是一个比较难以掌握的概念。先从一个简单的赋值讲起,其中house 和 mouse是key,同时house 和mouse也是一个变量,在ES5中是这样:
vardata=$('body').data(),//datahaspropertieshouseandmouse house=data.house, mouse=data.mouse;
以及在node.js中用ES5是这样:
varjsonMiddleware=require('body-parser').jsonMiddleware; varbody=req.body,//bodyhasusernameandpassword username=body.username, password=body.password;
在ES6,我们可以使用这些语句代替上面的ES5代码:
var{house,mouse}=$('body').data();//we'llgethouseandmousevariables var{jsonMiddleware}=require('body-parser'); var{username,password}=req.body;
这个同样也适用于数组,非常赞的用法:
var[col1,col2]=$('.column'), [line1,line2,line3,,line5]=file.split('n');
我们可能需要一些时间来习惯解构赋值语法的使用,但是它确实能给我们带来许多意外的收获。
7.Enhanced Object Literals (增强的对象字面量)in ES6
使用对象文本可以做许多让人意想不到的事情!通过ES6,我们可以把ES5中的JSON变得更加接近于一个类。
下面是一个典型ES5对象文本,里面有一些方法和属性:
varserviceBase={port:3000,url:'blog.yzmcms.com'}, getAccounts=function(){return[1,2,3]}; varaccountServiceES5={ port:serviceBase.port, url:serviceBase.url, getAccounts:getAccounts, toString:function(){ returnJSON.stringify(this.valueOf()); }, getUrl:function(){return""+this.url+':'+this.port}, valueOf_1_2_3:getAccounts() }
如果我们想让它更有意思,我们可以用Object.create从serviceBase继承原型的方法:
varaccountServiceES5ObjectCreate=Object.create(serviceBase) varaccountServiceES5ObjectCreate={ getAccounts:getAccounts, toString:function(){ returnJSON.stringify(this.valueOf()); }, getUrl:function(){return""+this.url+':'+this.port}, valueOf_1_2_3:getAccounts() }
我们知道,accountServiceES5ObjectCreate 和accountServiceES5 并不是完全一致的,因为一个对象(accountServiceES5)在proto对象中将有下面这些属性:
为了方便举例,我们将考虑它们的相似处。所以在ES6的对象文本中,既可以直接分配getAccounts: getAccounts,也可以只需用一个getAccounts,此外,我们在这里通过proto(并不是通过 proto')设置属性,如下所示:
varserviceBase={port:3000,url:'blog.yzmcms.com'}, getAccounts=function(){return[1,2,3]}; varaccountService={ __proto__:serviceBase, getAccounts,
另外,我们可以调用super防范,以及使用动态key值(valueOf_1_2_3):
toString(){ returnJSON.stringify((super.valueOf())); }, getUrl(){return""+this.url+':'+this.port}, ['valueOf_'+getAccounts().join('_')]:getAccounts() }; console.log(accountService)
ES6对象文本是一个很大的进步对于旧版的对象文本来说。
8. Promises in ES6
Promises 是一个有争议的话题。因此有许多略微不同的promise 实现语法。Q,bluebird,deferred.js,vow, avow, jquery 一些可以列出名字的。也有人说我们不需要promises,仅仅使用异步,生成器,回调等就够了。但令人高兴的是,在ES6中有标准的Promise实现。
下面是一个简单的用setTimeout()实现的异步延迟加载函数:
setTimeout(function(){ console.log('Yay!'); },1000);
在ES6中,我们可以用promise重写:
varwait1000=newPromise(function(resolve,reject){ setTimeout(resolve,1000); }).then(function(){ console.log('Yay!'); });
或者用ES6的箭头函数:
varwait1000=newPromise((resolve,reject)=>{ setTimeout(resolve,1000); }).then(()=>{ console.log('Yay!'); });
到目前为止,代码的行数从三行增加到五行,并没有任何明显的好处。确实,如果我们有更多的嵌套逻辑在setTimeout()回调函数中,我们将发现更多好处:
setTimeout(function(){ console.log('Yay!'); setTimeout(function(){ console.log('Wheeyee!'); },1000) },1000);
在ES6中我们可以用promises重写:
varwait1000=()=>newPromise((resolve,reject)=>{setTimeout(resolve,1000)}); wait1000() .then(function(){ console.log('Yay!') returnwait1000() }) .then(function(){ console.log('Wheeyee!') });
还是不确信Promises 比普通回调更好?其实我也不确信,我认为一旦你有回调的想法,那么就没有必要额外增加promises的复杂性。
虽然,ES6 有让人崇拜的Promises 。Promises 是一个有利有弊的回调但是确实是一个好的特性,更多详细的信息关于promise:Introduction to ES6 Promises.
9. Classes (类)in ES6
如果你喜欢面向对象编程(OOP),那么你将喜爱这个特性。以后写一个类和继承将变得跟在facebook上写一个评论那么容易。
类的创建和使用真是一件令人头疼的事情在过去的ES5中,因为没有一个关键字class (它被保留,但是什么也不能做)。在此之上,大量的继承模型像pseudo classical, classical, functional 更加增加了混乱,JavaScript 之间的宗教战争只会更加火上浇油。
用ES5写一个类,有很多种方法,这里就先不说了。现在就来看看如何用ES6写一个类吧。ES6没有用函数, 而是使用原型实现类。我们创建一个类baseModel ,并且在这个类里定义了一个constructor 和一个 getName()方法:
classbaseModel{ constructor(options,data){//classconstructor,node.js5.6暂时不支持options={},data=[]这样传参 this.name='Base'; this.url='www.yzmcms.com/api'; this.data=data; this.options=options; } getName(){//classmethod console.log(`Classname:${this.name}`); } }
注意我们对options 和data使用了默认参数值。此外方法名也不需要加function关键字,而且冒号(:)也不需要了。另外一个大的区别就是你不需要分配属性this。现在设置一个属性的值,只需简单的在构造函数中分配。
AccountModel 从类baseModel 中继承而来:
classAccountModelextendsbaseModel{ constructor(options,data){ //为了调用父级构造函数,可以毫不费力的唤起super()用参数传递: super({private:true},['32113123123','524214691']);//calltheparentmethodwithsuper this.name='AccountModel'; this.url+='/accounts/'; }
如果你想做些更好玩的,你可以把 accountData 设置成一个属性:
getaccountsData(){//calculatedattributegetter //...makeXHR returnthis.data; } }
那么,你如何调用他们呢?它是非常容易的:
letaccounts=newAccountModel(5); accounts.getName(); console.log('Datais%s',accounts.accountsData);
结果令人惊讶,输出是:
Classname:AccountModel Datais32113123123,524214691
10. Modules (模块)in ES6
众所周知,在ES6以前JavaScript并不支持本地的模块。人们想出了AMD,RequireJS,CommonJS以及其它解决方法。现在ES6中可以用模块import 和export 操作了。
在ES5中,你可以在 <script>中直接写可以运行的代码(简称IIFE),或者一些库像AMD。然而在ES6中,你可以用export导入你的类。下面举个例子,在ES5中,module.js有port变量和getAccounts 方法:
module.exports={ port:3000, getAccounts:function(){ ... } }
在ES5中,main.js需要依赖require(‘module') 导入module.js:
varservice=require('module.js'); console.log(service.port);//3000
但在ES6中,我们将用export and import。例如,这是我们用ES6 写的module.js文件库:
exportvarport=3000; exportfunctiongetAccounts(url){ ... }
如果用ES6来导入到文件main.js中,我们需用import {name} from ‘my-module'语法,例如:
import{port,getAccounts}from'module'; console.log(port);//3000
或者我们可以在main.js中把整个模块导入, 并命名为 service:
import*asservicefrom'module'; console.log(service.port);//3000
从我个人角度来说,我觉得ES6模块是让人困惑的。但可以肯定的事,它们使语言更加灵活了。
并不是所有的浏览器都支持ES6模块,所以你需要使用一些像jspm去支持ES6模块。
更多的信息和例子关于ES6模块,请看 this text。不管怎样,请写模块化的JavaScript。
如何使用ES6 (Babel)
ES6已经敲定,但并不是所有的浏览器都完全支持,详见:kangax.github.io/compat-table/es6/。要使用ES6,需要一个编译器例如:babel。你可以把它作为一个独立的工具使用,也可以把它放在构建中。grunt,gulp和webpack中都有可以支持babel的插件。
这是一个gulp案列,安装gulp-babel插件:
$npminstall--save-devgulp-babel
在gulpfile.js中,定义一个任务build,放入src/app.js,并且编译它进入构建文件中。
vargulp=require('gulp'), babel=require('gulp-babel'); gulp.task('build',function(){ returngulp.src('src/app.js') .pipe(babel()) .pipe(gulp.dest('build')); })
Node.js and ES6
在nodejs中,你可以用构建工具或者独立的Babel模块 babel-core 来编译你的Node.js文件。安装如下:
$npminstall--save-devbabel-core
然后在node.js中,你可以调用这个函数:
require("babel-core").transform(ES5Code,options);
ES6总结
这里还有许多ES6的其它特性你可能会使用到,排名不分先后:
1、全新的Math, Number, String, Array 和 Object 方法
2、二进制和八进制数据类型
3、默认参数不定参数扩展运算符
4、Symbols符号
5、tail调用
6、Generators (生成器)
7、New data structures like Map and Set(新的数据构造对像MAP和set)
以上就是ES6 十大特性简介的详细内容,更多关于ES6 特性的资料请关注易盾网络其它相关文章!
本文共计3956个文字,预计阅读时间需要16分钟。
ES6(ECMAScript 2015)的推出,为前端开发人员带来了诸多惊喜。它包含了许多酷炫的新特性,可简化实现复杂操作,提高开发效率。以下是对ES6的简要介绍:
ES6(ECMAScript2015)的出现,无疑给前端开发人员带来了新的惊喜,它包含了一些很棒的新特性,可以更加方便的实现很多复杂的操作,提高开发人员的效率。
本文主要针对ES6做一个简要介绍。
也许你还不知道ES6是什么, 实际上, 它是一种新的javascript规范。在这个大家都很忙碌的时代,如果你想对ES6有一个快速的了解,那么请继续往下读,去了解当今最流行的编程语言JavaScript最新一代的十大特性。
以下是ES6排名前十的最佳特性列表(排名不分先后):
1.Block-Scoped Constructs Let and Const(块作用域构造Let and Const)
2.Arrow Functions (箭头函数)in ES6
3.Default Parameters(默认参数) in ES6
4.Template Literals (模板文本)in ES6
5.Multi-line Strings (多行字符串)in ES6
6.Destructuring Assignment (解构赋值)in ES6
7.Enhanced Object Literals (增强的对象文本)in ES6
8.Promises in ES6
9.Classes(类) in ES6
10.Modules(模块) in ES6
首先回顾一下JavaScript的历史,不清楚历史的人,很难理解JavaScript为什么会这样发展。下面就是一个简单的JavaScript发展时间轴:
1、1995:JavaScript诞生,它的初始名叫LiveScript。
2、1997:ECMAScript标准确立。
3、1999:ES3出现,与此同时IE5风靡一时。
4、2000–2005: XMLHttpRequest又名AJAX, 在Outlook Web Access (2000)、Oddpost (2002),Gmail (2004)和Google Maps (2005)大受重用。
5、2009: ES5出现,(就是我们大多数人现在使用的)例如foreach,Object.keys,Object.create和JSON标准。
6、2015:ES6/ECMAScript2015出现。
历史回顾就先到此,现让我们进入正题。
1.Block-Scoped Constructs Let and Const(块作用域和构造let和const)
在ES6代码中,你可能已经看到那熟悉的身影let。在ES6里let并不是一个花俏的特性,它是更复杂的。Let是一种新的变量声明方式,它允许你把变量作用域控制在块级里面。我们用大括号定义代码块,在ES5中,块级作用域起不了任何作用:
functioncalculateTotalAmount(vip){ varamount=0; if(vip){ varamount=1; } {//morecrazyblocks! varamount=100; { varamount=1000; } } returnamount; } console.log(calculateTotalAmount(true)); 结果将返回1000,这真是一个bug。在ES6中,我们用let限制块级作用域。而var是限制函数作用域。 functioncalculateTotalAmount(vip){ varamount=0;//probablyshouldalsobelet,butyoucanmixvarandlet if(vip){ letamount=1;//firstamountisstill0 } {//morecrazyblocks! letamount=100;//firstamountisstill0 { letamount=1000;//firstamountisstill0 } } returnamount; } console.log(calculateTotalAmount(true));
这个结果将会是0,因为块作用域中有了let。如果(amount=1).那么这个表达式将返回1。谈到const,就更加容易了;它就是一个常量,也是块级作用域就像let一样。下面是一个演示,这里有一堆常量,它们互不影响,因为它们属于不同的块级作用域:
functioncalculateTotalAmount(vip){ constamount=0; if(vip){ constamount=1; } {//morecrazyblocks! constamount=100; { constamount=1000; } } returnamount; } console.log(calculateTotalAmount(true));
在传统的var中,一个变量可以多次重复声明,如果代码很长的话,出现变量重复声明的错误是很难排查出来的,而let和const都不可以重复声明,从我个人看来,let 和const在大型的代码排错中起着至关重要的作用。
2.Arrow Functions in(箭头函数) ES6
这是我迫不及待想讲的一个特征,CoffeeScript 就是因为它丰富的箭头函数让很多开发者喜爱。在ES6中,也有了丰富的箭头函数。这些丰富的箭头是令人惊讶的因为它们将使许多操作变成现实,比如,
以前我们使用闭包,this总是预期之外地产生改变,而箭头函数的迷人之处在于,现在你的this可以按照你的预期使用了,身处箭头函数里面,this还是原来的this。
有了箭头函数在ES6中, 我们就不必用that = this或 self = this 或 _this = this 或.bind(this)。例如,下面的代码用ES5就不是很优雅:
var_this=this; $('.btn').click(function(event){ _this.sendData(); }) 在ES6中就不需要用_this=this: $('.btn').click((event)=>{ this.sendData(); })
不幸的是,ES6委员会决定,以前的function的传递方式也是一个很好的方案,所以它们仍然保留了以前的功能。
下面这是一个另外的例子,我们通过call传递文本给logUpperCase() 函数在ES5中:
varlogUpperCase=function(){ var_this=this; this.string=this.string.toUpperCase(); returnfunction(){ returnconsole.log(_this.string); } } logUpperCase.call({string:'ES6rocks'})();
而在ES6,我们并不需要用_this浪费时间:
varlogUpperCase=function(){ this.string=this.string.toUpperCase(); return()=>console.log(this.string); } logUpperCase.call({string:'ES6rocks'})();
请注意,只要你愿意,在ES6中=>可以混合和匹配老的函数一起使用。当在一行代码中用了箭头函数,它就变成了一个表达式。它将暗地里返回单个语句的结果。如果你超过了一行,将需要明确使用return。
这是用ES5代码创建一个消息数组:
varids=['5632953c4e345e145fdf2df8','563295464e345e145fdf2df9']; varmessages=ids.map(function(value){ return"IDis"+value;//explicitreturn });
用ES6是这样:
varids=['5632953c4e345e145fdf2df8','563295464e345e145fdf2df9']; varmessages=ids.map(value=>`IDis${value}`);//implicitreturn
请注意,这里用了字符串模板。
在箭头函数中,对于单个参数,括号()是可选的,但当你超过一个参数的时候你就需要他们。
在ES5代码有明确的返回功能:
varids=['5632953c4e345e145fdf2df8','563295464e345e145fdf2df9']; varmessages=ids.map(function(value,index,list){ return'IDof'+index+'elementis'+value+'';//explicitreturn });
在ES6中有更加严谨的版本,参数需要被包含在括号里并且它是隐式的返回:
varids=['5632953c4e345e145fdf2df8','563295464e345e145fdf2df9']; varmessages=ids.map((value,index,list)=>`IDof${index}elementis${value}`);//implicitreturn
3.Default Parameters(默认参数) in ES6
还记得我们以前不得不通过下面方式来定义默认参数:
varlink=function(height,color,url){ varheight=height||50; varcolor=color||'red'; varurl=url||'www.yzmcms.com'; ... }
一切工作都是正常的,直到参数值是0后,就有问题了,因为在JavaScript中,0表示fasly,它是默认被hard-coded的值,而不能变成参数本身的值。当然,如果你非要用0作为值,我们可以忽略这一缺陷并且使用逻辑OR就行了!但在ES6,我们可以直接把默认值放在函数申明里:
varlink=function(height=50,color='red',url='www.yzmcms.com'){ ... }
顺便说一句,这个语法跟PHP中是一样的!
4.Template Literals(模板对象) in ES6
在其它语言中,使用模板和插入值是在字符串里面输出变量的一种方式。因此,在ES5,我们可以这样组合一个字符串:
varname='Yournameis'+first+''+last+'.'; varurl='blog.yzmcms.com/api/messages/'+id;
幸运的是,在ES6中,我们可以使用新的语法$ {NAME},并把它放在反引号里:
varname=`Yournameis${first}${last}.`; varurl=`blog.yzmcms.com/api/messages/${id}`;
5.Multi-line Strings (多行字符串)in ES6
ES6的多行字符串是一个非常实用的功能。在ES5中,我们不得不使用以下方法来表示多行字符串:
varroadPoem='Thentooktheother,asjustasfair,nt' +'Andhavingperhapsthebetterclaimnt' +'Becauseitwasgrassyandwantedwear,nt' +'Thoughasforthatthepassingtherent' +'Hadwornthemreallyaboutthesame,nt'; varfourAgreements='Youhavetherighttobeyou.n Youcanonlybeyouwhenyoudoyourbest.';
然而在ES6中,仅仅用反引号就可以解决了:
varroadPoem=`Thentooktheother,asjustasfair, Andhavingperhapsthebetterclaim Becauseitwasgrassyandwantedwear, Thoughasforthatthepassingthere Hadwornthemreallyaboutthesame,`; varfourAgreements=`Youhavetherighttobeyou. Youcanonlybeyouwhenyoudoyourbest.`;
6.Destructuring Assignment (解构赋值)in ES6
解构可能是一个比较难以掌握的概念。先从一个简单的赋值讲起,其中house 和 mouse是key,同时house 和mouse也是一个变量,在ES5中是这样:
vardata=$('body').data(),//datahaspropertieshouseandmouse house=data.house, mouse=data.mouse;
以及在node.js中用ES5是这样:
varjsonMiddleware=require('body-parser').jsonMiddleware; varbody=req.body,//bodyhasusernameandpassword username=body.username, password=body.password;
在ES6,我们可以使用这些语句代替上面的ES5代码:
var{house,mouse}=$('body').data();//we'llgethouseandmousevariables var{jsonMiddleware}=require('body-parser'); var{username,password}=req.body;
这个同样也适用于数组,非常赞的用法:
var[col1,col2]=$('.column'), [line1,line2,line3,,line5]=file.split('n');
我们可能需要一些时间来习惯解构赋值语法的使用,但是它确实能给我们带来许多意外的收获。
7.Enhanced Object Literals (增强的对象字面量)in ES6
使用对象文本可以做许多让人意想不到的事情!通过ES6,我们可以把ES5中的JSON变得更加接近于一个类。
下面是一个典型ES5对象文本,里面有一些方法和属性:
varserviceBase={port:3000,url:'blog.yzmcms.com'}, getAccounts=function(){return[1,2,3]}; varaccountServiceES5={ port:serviceBase.port, url:serviceBase.url, getAccounts:getAccounts, toString:function(){ returnJSON.stringify(this.valueOf()); }, getUrl:function(){return""+this.url+':'+this.port}, valueOf_1_2_3:getAccounts() }
如果我们想让它更有意思,我们可以用Object.create从serviceBase继承原型的方法:
varaccountServiceES5ObjectCreate=Object.create(serviceBase) varaccountServiceES5ObjectCreate={ getAccounts:getAccounts, toString:function(){ returnJSON.stringify(this.valueOf()); }, getUrl:function(){return""+this.url+':'+this.port}, valueOf_1_2_3:getAccounts() }
我们知道,accountServiceES5ObjectCreate 和accountServiceES5 并不是完全一致的,因为一个对象(accountServiceES5)在proto对象中将有下面这些属性:
为了方便举例,我们将考虑它们的相似处。所以在ES6的对象文本中,既可以直接分配getAccounts: getAccounts,也可以只需用一个getAccounts,此外,我们在这里通过proto(并不是通过 proto')设置属性,如下所示:
varserviceBase={port:3000,url:'blog.yzmcms.com'}, getAccounts=function(){return[1,2,3]}; varaccountService={ __proto__:serviceBase, getAccounts,
另外,我们可以调用super防范,以及使用动态key值(valueOf_1_2_3):
toString(){ returnJSON.stringify((super.valueOf())); }, getUrl(){return""+this.url+':'+this.port}, ['valueOf_'+getAccounts().join('_')]:getAccounts() }; console.log(accountService)
ES6对象文本是一个很大的进步对于旧版的对象文本来说。
8. Promises in ES6
Promises 是一个有争议的话题。因此有许多略微不同的promise 实现语法。Q,bluebird,deferred.js,vow, avow, jquery 一些可以列出名字的。也有人说我们不需要promises,仅仅使用异步,生成器,回调等就够了。但令人高兴的是,在ES6中有标准的Promise实现。
下面是一个简单的用setTimeout()实现的异步延迟加载函数:
setTimeout(function(){ console.log('Yay!'); },1000);
在ES6中,我们可以用promise重写:
varwait1000=newPromise(function(resolve,reject){ setTimeout(resolve,1000); }).then(function(){ console.log('Yay!'); });
或者用ES6的箭头函数:
varwait1000=newPromise((resolve,reject)=>{ setTimeout(resolve,1000); }).then(()=>{ console.log('Yay!'); });
到目前为止,代码的行数从三行增加到五行,并没有任何明显的好处。确实,如果我们有更多的嵌套逻辑在setTimeout()回调函数中,我们将发现更多好处:
setTimeout(function(){ console.log('Yay!'); setTimeout(function(){ console.log('Wheeyee!'); },1000) },1000);
在ES6中我们可以用promises重写:
varwait1000=()=>newPromise((resolve,reject)=>{setTimeout(resolve,1000)}); wait1000() .then(function(){ console.log('Yay!') returnwait1000() }) .then(function(){ console.log('Wheeyee!') });
还是不确信Promises 比普通回调更好?其实我也不确信,我认为一旦你有回调的想法,那么就没有必要额外增加promises的复杂性。
虽然,ES6 有让人崇拜的Promises 。Promises 是一个有利有弊的回调但是确实是一个好的特性,更多详细的信息关于promise:Introduction to ES6 Promises.
9. Classes (类)in ES6
如果你喜欢面向对象编程(OOP),那么你将喜爱这个特性。以后写一个类和继承将变得跟在facebook上写一个评论那么容易。
类的创建和使用真是一件令人头疼的事情在过去的ES5中,因为没有一个关键字class (它被保留,但是什么也不能做)。在此之上,大量的继承模型像pseudo classical, classical, functional 更加增加了混乱,JavaScript 之间的宗教战争只会更加火上浇油。
用ES5写一个类,有很多种方法,这里就先不说了。现在就来看看如何用ES6写一个类吧。ES6没有用函数, 而是使用原型实现类。我们创建一个类baseModel ,并且在这个类里定义了一个constructor 和一个 getName()方法:
classbaseModel{ constructor(options,data){//classconstructor,node.js5.6暂时不支持options={},data=[]这样传参 this.name='Base'; this.url='www.yzmcms.com/api'; this.data=data; this.options=options; } getName(){//classmethod console.log(`Classname:${this.name}`); } }
注意我们对options 和data使用了默认参数值。此外方法名也不需要加function关键字,而且冒号(:)也不需要了。另外一个大的区别就是你不需要分配属性this。现在设置一个属性的值,只需简单的在构造函数中分配。
AccountModel 从类baseModel 中继承而来:
classAccountModelextendsbaseModel{ constructor(options,data){ //为了调用父级构造函数,可以毫不费力的唤起super()用参数传递: super({private:true},['32113123123','524214691']);//calltheparentmethodwithsuper this.name='AccountModel'; this.url+='/accounts/'; }
如果你想做些更好玩的,你可以把 accountData 设置成一个属性:
getaccountsData(){//calculatedattributegetter //...makeXHR returnthis.data; } }
那么,你如何调用他们呢?它是非常容易的:
letaccounts=newAccountModel(5); accounts.getName(); console.log('Datais%s',accounts.accountsData);
结果令人惊讶,输出是:
Classname:AccountModel Datais32113123123,524214691
10. Modules (模块)in ES6
众所周知,在ES6以前JavaScript并不支持本地的模块。人们想出了AMD,RequireJS,CommonJS以及其它解决方法。现在ES6中可以用模块import 和export 操作了。
在ES5中,你可以在 <script>中直接写可以运行的代码(简称IIFE),或者一些库像AMD。然而在ES6中,你可以用export导入你的类。下面举个例子,在ES5中,module.js有port变量和getAccounts 方法:
module.exports={ port:3000, getAccounts:function(){ ... } }
在ES5中,main.js需要依赖require(‘module') 导入module.js:
varservice=require('module.js'); console.log(service.port);//3000
但在ES6中,我们将用export and import。例如,这是我们用ES6 写的module.js文件库:
exportvarport=3000; exportfunctiongetAccounts(url){ ... }
如果用ES6来导入到文件main.js中,我们需用import {name} from ‘my-module'语法,例如:
import{port,getAccounts}from'module'; console.log(port);//3000
或者我们可以在main.js中把整个模块导入, 并命名为 service:
import*asservicefrom'module'; console.log(service.port);//3000
从我个人角度来说,我觉得ES6模块是让人困惑的。但可以肯定的事,它们使语言更加灵活了。
并不是所有的浏览器都支持ES6模块,所以你需要使用一些像jspm去支持ES6模块。
更多的信息和例子关于ES6模块,请看 this text。不管怎样,请写模块化的JavaScript。
如何使用ES6 (Babel)
ES6已经敲定,但并不是所有的浏览器都完全支持,详见:kangax.github.io/compat-table/es6/。要使用ES6,需要一个编译器例如:babel。你可以把它作为一个独立的工具使用,也可以把它放在构建中。grunt,gulp和webpack中都有可以支持babel的插件。
这是一个gulp案列,安装gulp-babel插件:
$npminstall--save-devgulp-babel
在gulpfile.js中,定义一个任务build,放入src/app.js,并且编译它进入构建文件中。
vargulp=require('gulp'), babel=require('gulp-babel'); gulp.task('build',function(){ returngulp.src('src/app.js') .pipe(babel()) .pipe(gulp.dest('build')); })
Node.js and ES6
在nodejs中,你可以用构建工具或者独立的Babel模块 babel-core 来编译你的Node.js文件。安装如下:
$npminstall--save-devbabel-core
然后在node.js中,你可以调用这个函数:
require("babel-core").transform(ES5Code,options);
ES6总结
这里还有许多ES6的其它特性你可能会使用到,排名不分先后:
1、全新的Math, Number, String, Array 和 Object 方法
2、二进制和八进制数据类型
3、默认参数不定参数扩展运算符
4、Symbols符号
5、tail调用
6、Generators (生成器)
7、New data structures like Map and Set(新的数据构造对像MAP和set)
以上就是ES6 十大特性简介的详细内容,更多关于ES6 特性的资料请关注易盾网络其它相关文章!

