ES6(ECMAScript2015)的出现,让前端开发者收到一份惊喜,它简洁的新语法、强大的新特性,带给我们更便捷和流畅的编码体验。
下面让我们一起学习这十个最经典和试用的ES6新特性。
//ES5 我们这样定义默认参数
var link = function(height, color, url) {
var height = height || 50;
var color = color || 'red';
var url = url || 'http://aaa.com';
···
}
这样做是有一点小问题的,当默认参数为0时就暴露出问题了,因为在JavaScript中,0表示false。
//ES6 可以把默认值写在函数声明中
var link = function(height = 50, color = 'red', url = 'http://aaa.com') {
···
}
//ES5的字符串拼接
var name = 'Your name is ' + first + ' ' + last + '.';
var url = 'http://localhost:3000/api/messages/' + id;
ES6的字符串不需要这么麻烦,我们可以在反引号(英文的shift + ~)中使用新语法${变量名称}
表示。
//ES6
var name = 'Your name is ${first} ${last}. ';
var url = 'http://localhost:3000/api/messages/${id}';
// ES5 多行字符串需要 + 号连接
var roadPoem = 'Then took the other, as just as fair,nt'
+ 'And having perhaps the better claimnt'
+ 'Because it was grassy and wanted wear,nt'
+ 'Though as for that the passing therent'
+ 'Had worn them really about the same,nt';
var fourAgreements = 'You have the right to be you.n
You can only be you when you do your best.';
然而在ES6中,仅仅用反引号就可以搞定
var roadPoem = `Then took the other, as just as fair,
And having perhaps the better claim
Because it was grassy and wanted wear,
Though as for that the passing there
Had worn them really about the same,`;
var fourAgreements = `You have the right to be you.
You can only be you when you do your best.`;
这是一个比较难掌握的知识点,我们先用比较简单的例子切入。
下面这些情况都是很常见的:
//ES5 中获取data对象中的属性
var data = response.data,
info = data.info,
imageLink = data.imageLink;
//ES5中获取一个模块中的方法
var stringHandle = require('toolModule').stringHandle;
ES6中,我们可以使用解构处理上述两种情况:
var { info, imageLink } = response.data;
var { stringHandle } = require('toolModuole');
首先要保证右侧的response.data
和require('toolModule')
与左侧的{}
格式相同(这里全都是对象)。个人理解{ info, imageLink } = response.data
就像是{ info, imageLink } = { response.data.info, response.data.imageLink }
这样一一对应的关系,然后我们就可以直接使用info
和imageLink
这两个变量了。
解构还有很多高级用法,深入学习请移步http://es6.ruanyifeng.com/#docs/destructuring
下面是一个典型的ES5对象文本,里面有一些方法和属性:
var serviceBase = { port: 3000, url: 'azat.com'},
getAccounts = function() { return [1, 2, 3] };
var accountServiceES5 = {
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 accountServiceES5ObjectCreate = Object.create(serviceBase)
var accountServiceES5ObjectCreate = {
getAccounts: getAccounts,
toString: function() {
return JSON.stringify(this.valueOf());
},
getUrl: function() {
return "http://" + this.url + ':' + this.port
},
valueOf_1_2_3: getAccounts()
}
以前我们使用闭包,this总是预期之外的产生改变,而箭头函数的迷人之处在于,现在你的this可以按照你的预期使用了,身处箭头函数里面,this还是原来的this。
有了箭头函数在ES6中,我们就不必再用that = this
或者self = this
或者_this = this
//ES5中
var _this = this;
$('btn').click(function() {
_this.sendMessage();
})
而在ES6中我么可以这么写
$('btn').click(fucntion() {
this.sendMessage();
})
Promises是一个有争议的话题。因此有许多略微不同的promises实现与法。也有人说我们不需要promises,仅仅使用异步、生成器、回调等就够了。但在ES6中有了标准的Promises实现。
下面是一个简单的setTimeout()实现异步延迟加载:
setTimeout(function() {
console.log('I`m setTimeout')
}, 1000)
在ES6中我们可以用Promises进行重写
var delay = new Promise(function(resolve, reject) {
setTimeout(resolve, 1000);
}).then(fucntion() {
console.log('I`m setTimeout')
})
还可以用ES6的箭头函数:
var delay = new Promise((resolve, reject)=> {
setTimeout(resolve, 1000);
}).then(()=> {
console.log('I`m setTimeout')
})
①Let:在ES6代码中,let
是一种新的变量声明方式,它允许你把变量作用域控制在块级里面。
在ES5中,花括号的块级作用域起不了任何作用:
function calculateTotalAmount(vip) {
var amount = 0;
if(vip) {
var amount = 1;
}
{
var amount = 100;
{
var amount = 1000;
}
}
return amount;
}
console.log(calculateToAmount(true)); //1000,最后定义的生效,块级作用域没效果
块级作用域中let
定义的变量,只在此块级作用域中生效,外层无法访问。
function calculateTotalAmount (vip) {
var amount = 0;
if (vip) {
let amount = 1;
}
{
let amount = 100;
{
let amount = 1000;
}
}
return amount;
}
console.log(calculateToAmount(true)); // 0,用let定义的变量不可被外层访问
注意:值得一提的是,当if语句变为if(vip) { amount = 1 }
那么结果是1,因为这样就相当于定义了一个全局变量。
②Const:const
用于声明常量,同一个常量只能声明一次,声明之后不可修改。而下面的代码中对于同一个常量声明了多次,却没有报错,原因就是每个常量都只属于他所在的块级作用域,互不影响。
function calculateTotalAmount(vip) {
const amount = 0;
if(vip) {
const amount = 1;
}
{
const amount = 100;
{
const amount = 1000;
}
}
return amount;
}
console.log(calculateTotalAmount(true)); // 0
下面来看ES6如何创建一个类。ES6中没用使用函数,而是使用原型实现类。我们创建一个类baseModel
,并且在这个类里面定义一个constructor
和一个getName()
方法:
class baseModel {
constructor(options, data) {
this.name = 'Base';
this.url = 'http://baseurl.com/api';
this.options = options;
this.data = data;
}
getName() {
console.log(`Class name is: ${this.name}`);
}
}
我们让AccountModel继承baseModel:
class AccountMode extends baseModel {
constructor(options, data) {
//为了调用父级构造函数,可以用super()进行传参
super({private: true}, ['123123', '456456']);
this.name = 'Account Model';
this.url += '/accounts/';
}
// 可以把accountData设置成一个属性
get accountsData() {
return this.data;
}
}
let accounts = new AccountModel(5);
accounts.getName(); //Class name is: Account Model
console.log('Data is: ', accounts.accountsData); //Data is 123123, 456456
众所周知,在ES6之前JavaScript并不支持本地模块。大家想出了AMD,RequireJs,CommonJS以及其他解决办法。在ES6中我们可以使用import
和export
进行操作了。
在ES5中,我们可以在中直接写可以运行的代码(简称IIFE),或者一些库。然而在ES6中,我们可以用
import
导入你的类。
举个例子:在ES5中,moduel.js有port变量和getAccounts方法
// dev.js文件
module.exports = {
port: 3000,
getAccounts: function() {
···
}
}
在ES5中需要依赖require(‘module’)导入dev.js:
var service = require('dev.js');
console.log(service.port); // 3000
然而在ES6中,我们使用export
和import
进行操作
// dev.js
export var port = 3000;
export function getAccounts(url) { ··· }
下面我们使用ES6中的import
来导入dev.js文件,我们需要用import {name} from 'my-module’语法:
import {port, getAccounts} from 'dev';
console.log(port); // 3000
或者我们把整个模块导入,并且命名为service:
import * as service from 'dev';
console.log(service.port); // 3000