目前不使用Es7的主要原因是大量浏览器仅支持ES 6或者ES5版本。
1、为什么要使用Es6 ,是一次重大的版本升级,它秉承着最大化兼容已有代码的设计理念。过去编写的JS代码还能正常运行。。可以更加方便的实现很多复杂的操作,提高开发人员的效率
ES6排名前十位的最佳特性列表
- Default Parametes (默认参数)
- Template Literals (模板文本)
- Multi-line Strings(多行字符串)
- Destructuring Assignment (解构赋值)
- Enhanced Object Literals (增强的对象文本)
- Arrow Functions (箭头函数)
- Promises in ES 6
- Block-Scoped Constructs Let and Const (块作用域构造)
- Classes(类)
- Modules(模块)
2.简单用法:
1、可以把默认值放在函数声明里
var link = function(height = 50, color = 'red', url='http://baidu.com'){
.....
}
2、
ES6之前方式只能使用组合字符串方法
var name = 'Your name is' + first + ' '+ last + ' . ';
ES6中,可以使用新的语法 ${name} ,并将其放在反引号里;
var name = `Your name is ${first} ${last}`;
3、用反引号解决多行字符串
Es5多行字符串表达
var roadPoem = '李悝,'
+ '关关雎鸠。'
+ '春来江水绿如蓝。'
+ '能不忆江南?
var roadPoem = `李悝,
关关雎鸠。
春来江水绿如蓝。
能不忆江南?
`
4、解构赋值
解构可能是一个比较难以掌握的概念,先从简单的赋值讲起,其中house和mouse 是key,同时house和mouse也是一个变量,在Es5中是这样的:
var data = $('body').data(); //data拥有两个属性house和mouse
house = data.house;
mouse = data.mouse;
在Node.js中用ES5是这样的:
var jsonMiddleware = require('body-parser').jsonMiddleware;
var body = req.body; //body两个属性username和password
username = body.username;
password = body.password;
在ES6中,可以使用以下语句来代替上面ES5代码
var {house,mouse} = $('body').data();
var {jsonmiddleware} = require('body-parser');
var {username, password} = req.body;
这个也同样适用于数组:
var [col1, col2] = $('.column'),
[line1, line2, line3, , line5] = file.split('n');
5、增强的对象文本
下面是ES5对象文本:
//文本对象
var serviceBase = {port: 3000, url: 'baidu.com'},
getAccounts = function() {
return [1,2,3]
}
var accountServiceES 5 = {
port: serviceBase.port,
url: serviceBase.url,
getAccounts: getAccounts,
toString: function() {
return JSON.stringify(this.valueOf());
},
getUrl: function() {
return "http://" + this.url + ':' + this.port
},
valueOf_1_2_3: getAccounts()
}
如果开发者想让它更有意思,可以用Object.create 从ServiceBase继承原型的方法:
var accountServiceES 5objectCreate = Object.create(serviceBase)
var accountServiceES 5objectCreate = {
getAccoutns: getAccounts,
toString: function() {
return JSON.stringify(this.valueOf());
},
getUrl: function(){
return "http://" + this.url + ':' + this.port
},
valueOf_1_2_3: getAccounts();
}
其实对于以上两种并不是完全一致的。Object.Create()方法创建一个新对象,其是使用现有的对象来继承创建一个新的对象,而accountService ES 5 并且继承现有对象。
所以在Es6 的对象文本中,既可以直接分配getAccounts:getAccounts,也可以只需用一个getAccounts。此外,可以通过_ proto_并不是通过(proto)设置属性:
var serviceBase = {port: 3000, url: 'baidu.com'},
getAccounts = function() {return [1,2,3]};
var accountService = {
_proto_:serviceBase,
getAccounts,
//另外,可以调用super防范,以及使用动态key值(valueOf_1_2_3);
toString() {
return JSON.stringify((super.valueOf()));
},
getUrl() {
return "http://" + this.url + ':' +this.port
},
[ 'valueOf_' + getAccounts().join('_') ]: getAccounts()
};
console.log(accountService)
6、箭头函数
在ES6中,有丰富的箭头函数。比如,以前我们使用闭包,this总是预期之外的改变,而箭头函数的好处在于,现在this可以按照你的预期使用了,深处箭头函数里,this还是原来的this。
有了箭头函数,我们就不必用that=this或self=this、_this=this那么麻烦了。
下面是ES5
var _this = this;
$('.btn').click(function(event){
_this.sendData();
})
在ES6中则不需要用_this = this;
$('.btn').click((event) => {
this.sendData();
})
但不是完全否定之前的方案,ES6委员会决定,以前的function的传递方式也是一个很好的方案,所以它们仍然保留了以前的功能。
下面是另一个例子,通过call传递文本给logUpperCase()函数,在ES5中:
var logUpperCase = function(){
var _this = this;
this.string = this.string.toUpperCase();
return function() {
return console.log(_this.string);
}
}
logUpperCase.call({string: 'ES 6 rocks'}) ();
而在ES6中并不需要用_this浪费时间:
var logUpperCase = function() {
this.string = this.string.toUpperCase();
return () => console.log(this.string);
}
logUpperCase.call({string: 'ES 6 rocks'})();
注意!!在ES6中,=>可以混合和匹配老的函数一起使用。当在一行代码中用了箭头函数后,它就变成了一个表达式,其将暗中返回单个语句的结果。如果结果超过一行,将需要明确使用return
在箭头函数中,对于单个参数,括号是可省略的,但当参数超过一个时就需要括号了。在ES5代码中有明确的返回功能:
var ids = ['5687868csdfsfisoduf', 'jsdlksjdk234234lk42jk34'];
var messages = ids.map(function (value, index, list){
return 'ID of' + index + 'elment is' + value+ ' ';
})
在ES6中有更加严谨的版本,参数需要被包含在括号里并且是隐式地返回:
var ids =['5687868csdfsfisoduf', 'jsdlksjdk234234lk42jk34'];
var messages = ids.map((value, index, list) => `ID of ${index} element is ${value}`); //隐式返回
7、Promise实现
下面是一个简单的用setTimeout()函数实现的异步延迟加载函数:
setTimeout(function () {
console.log('Yay!');
},1000);
在ES6中,可以用Promise重写,虽然在此实例中并不能减少大量的代码。甚至多些了数行,但是逻辑却清晰了不少:
var wait1000 = new Promise((resolve, reject) => {
setTimeout(resolve, 1000);
}).then(()=> {
console.log('Yay!');
})
8、块作用域let
在ES6中,let并不是一个“花哨”的特性,是更复杂的。let是一种新的变量声明方式,允许我们把变量作用域控制在块级里面,用大括号定义代码块,在ES5中,块级作用域起步了任何作用:
function calculateTotalAmount (vip) {
//只能使用var方式定义变量
var amount = 0;
if(vip) {
//在此定义会覆盖
var amount = 1;
}
{
//在此定义会覆盖
var amount = 1000;
{
//在此定义会覆盖
var amount = 10000;
}
}
return amount;
}
//打印输出内容
console.log(calculateTotalAmount(true));
以上代码结果将返回1000,这真是一个bug。在ES6中,用let限制块级作用域,而var限制函数作用域。
function calculateTotalAmount (vip) {
//使用var方式定义变量
var amount = 0;
if (vip) {
//使用let定义的局部变量
let amount = 1; //第1个let
}
{
let amount = 100; //第2个let
{
let amount = 1000; //第3个let
}
}
return amount;
}
console.log(calculateTotalAmount(true));
程序结果将会是0.因为块作用域中有了let,如果(amount=1),那么这个表达式将返回1。
9、类
在之前的javascript版本中,对于类的创建和使用时令人非常头疼的一件事。不同于直接使用class命名一个类的语言(在javascript中class关键字被保留,但是没有任何作用),因为没有官方的类功能,加上大量继承模型的出现,造成了jaascript类使用的困难和不规范。
用ES6写一个类,ES6没有用函数,而是使用原型实现类,我们创建一个类baseModel,并且在这个类里定义一个constructor()和一个getName()方法:
class baseModel {
constructor(options, data ){ //class constructor,Node.js 5.6暂时不支持options = { }, data = [ ]这样传参
this.name = 'Base';
this.url = 'http://baidu.com/api';
this.data = data;
this.options = options;
}
getName() {
console.log(`Class name: ${this.name}`)
}
}
!!!这里对options和data使用了默认参数值,方法名也不需要加function关键字,而且冒号“:”也不需要了;另一个大的区别就是不需要分配属性this。现在设置一个属性的值,只需简单的在构造函数中分配即可。
10、模块
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:
var service = require('module.js');
console.log(service.port);
但在ES6中,将用export and import进行一个模块的引入和抛出。例如,以下是用ES6写的module.js文件库:
export var port = 3000;
export function getAccounts(url) {
...
}
如果用ES6将上述的module.js导入到文件main.js中,就变得非常简单了,只需要用import { port,getAccounts} from 'module';
console.log(port); //3000
或者可以在main.js中导入整个模块,并命名为service:
import * as service from 'module';
console.log(service.port); //3000