ES6中比較實(shí)用的八個(gè)特性:
1.塊級作用域的let和const
2.箭頭函數(shù)
3.默認(rèn)參數(shù)
4.模版表達(dá)式
5.多行字符串
6.Promise
7.類
8.模塊化
1. 塊級作用域的let和const
let是一個(gè)更新的var,可以讓你把變量作用域限制在當(dāng)前塊里。我們用{}來定義塊,但是在ES5中這些花括號起不到任何作用。
function test (e) {
var num = 0
if (e) {
var num = 1
}
{ // 更多的塊
var num = 10
{
var num = 100
}
}
return num
}
console.log(test(true))
運(yùn)行結(jié)果將會(huì)是100,簡直變態(tài)···
在ES6中,我們用let來限制變量作用域?yàn)楹瘮?shù)內(nèi)。
function test (e) {
let num = 0
if (e) {
let num = 1
}
{ // 更多的塊
let num = 10
{
let num = 100
}
}
return num
}
console.log(test(true))
運(yùn)行結(jié)果是0。
說到const,就簡單多了。他僅僅產(chǎn)生是一個(gè)不可變的變量,并且他的作用域也像let一樣只有塊級。為了演示,這里有定義了一堆常量,并且由于作用域的原因,這些定義都是有效的。
function test(e) {
const num = 0
if (e) {
const num = 1
}
{ // 更多的塊
const num = 10
{
const num = 100
}
}
return num
}
console.log(test(true))
let和const讓這門語言變得更加復(fù)雜,沒有這些的時(shí)候我們只有一條路可以走,但是現(xiàn)在可以要考慮更多的情景。
2. ES6中的箭頭函數(shù)
這些箭頭最神奇的地方在于他會(huì)讓你寫正確的代碼。比如,this
在上下文和函數(shù)中的值應(yīng)當(dāng)是相同的,它不會(huì)變化,通常變化的原因都是因?yàn)槟銊?chuàng)建了閉包。
使用箭頭函數(shù)可以讓我們不再用that = this
或者self = this
或者_(dá)this = this
或者.bind(this)
這樣的代碼,比如,這些代碼在ES5中就特別丑。
var _this = this
$('.btn').click(function(event){
_this.sendData()
})
這是在ES6中去掉_this = this
之后:
$('.btn').click((event) =>{
this.sendData()
})
注意,在ES6中你可以合理的把箭頭函數(shù)和舊式 function 函數(shù)混用。當(dāng)箭頭函數(shù)所在語句只有一行時(shí),它就會(huì)變成一個(gè)表達(dá)式,它會(huì)直接返回這個(gè)語句的值。但是如果你有多行語句,你就要明確的使用return。
3. ES6中的默認(rèn)參數(shù)
以前我們要這樣子來定義默認(rèn)參數(shù):
var link = function (height, color, url) {
var height = height || 100
var color = color || 'skyblue'
var url = url || 'http://baidu.com'
...
}
在ES6中,我們可以把這些默認(rèn)值直接放在函數(shù)簽名中。
var link = function(height = 100, color = 'skyblue', url = 'http://baidu.com') {
...
}
4. ES6中的模版表達(dá)式
在ES5中,我們非得把字符串破開變成這樣:
var name = 'Your name is ' + first + ' ' + last + '.'
var url = 'http://localhost:3000/api/messages/' + id
在ES6中我們有了新語法,在反引號包裹的字符串中,使用${name}語法來表示模板字符:
var name = `Your name is ${first} ${last}`
var url = `http://localhost:3000/api/messages/${id}`
5. ES6中的多行字符串
在ES5中想要實(shí)現(xiàn)多行字符串我們需要這樣:
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.`
6. ES6中的Promise
在ES6中有一個(gè)標(biāo)準(zhǔn)的Promise實(shí)現(xiàn),可以解決嵌套過深的問題。
舉一個(gè)延遲異步執(zhí)行,用setTimeout實(shí)現(xiàn):
setTimeout(function(){
console.log('Hi!')
}, 1000)
我們可以用ES6中的Promise重寫:
var wait1000 = new Promise(function(resolve, reject) {
setTimeout(resolve, 1000)
}).then(function() {
console.log('Hi!')
})
或者用ES6的箭頭函數(shù):
var wait1000 = new Promise((resolve, reject)=> {
setTimeout(resolve, 1000)
}).then(()=> {
console.log('Hi!')
})
到現(xiàn)在為止,我們只是單純增加了代碼的行數(shù),還明顯沒有帶來任何好處。但是如果我們有更多復(fù)雜的邏輯內(nèi)嵌在setTimeout()
中的回調(diào)時(shí)好處就來了:
setTimeout(function(){
console.log('Yay!')
setTimeout(function(){
console.log('Wheeyee!')
}, 1000)
}, 1000)
可以用ES6中的Promise重寫:
var wait1000 = ()=> new Promise((resolve, reject)=> {setTimeout(resolve, 1000)})
wait1000()
.then(function() {
console.log('Yay!')
return wait1000()
})
.then(function() {
console.log('Wheeyee!')
});
7. ES6中的類
在ES5中,因?yàn)闆]有class關(guān)鍵字(但它是毫無作用的保留字),類的創(chuàng)建和使用十分麻煩。ES6的類會(huì)用prototype來實(shí)現(xiàn)而不是function?,F(xiàn)在有一個(gè)baseModel類,其中我們可以定義構(gòu)造函數(shù)和getName()
方法。
class baseModel {
constructor(options = {}, data = []) { // class 屬性
this.name = 'Base'
this.url = 'http://baidu.com'
this.data = data
this.options = options
}
getName() { // class 方法
console.log(`Class name: ${this.name}`)
}
}
options和data用了默認(rèn)參數(shù),
而且方法名再也不用加上function。
8. ES6中的模塊化
ES6之前JavaScript并沒有對模塊化有過原生的支持,于是有人創(chuàng)造出AMD(RequireJS),CommenJS等等,現(xiàn)在終于有import和export運(yùn)算符來實(shí)現(xiàn)了。
ES5中你會(huì)用script標(biāo)簽和IIFE(立即執(zhí)行函數(shù)),或者是其他的像AMD之類的庫,但是ES6中你可以用export來暴露你的類。然后用Browserfy來瀏覽器化。
比如我們有一個(gè)port變量和getAccounts方法,在ES5中需要這么實(shí)現(xiàn):
module.exports = {
port: 3000,
getAccounts: function() {
...
}
}
在ES5的main.js中,用require('模塊')來導(dǎo)入:
var service = require('module.js')
console.log(service.port) // 3000
但是在ES6中,我們用export和import。比如這是ES6中的module.js文件:
export var port = 3000
export function getAccounts(url) {
...
}
在需要引入的main.js文件中,可以用import {名稱} from '模塊'語法:
import {port, getAccounts} from 'module'
console.log(port) // 3000
或者就直接在main.js
中引入所有的變量:
import * as service from 'module'
console.log(service.port) // 3000
由于現(xiàn)在的大部分瀏覽器還不支持ES6,,如果想馬上就用上ES6,我們需要一個(gè)像Babel這樣的編譯器。你可以把他當(dāng)獨(dú)立工具用,也可以將他集成到構(gòu)建系統(tǒng)里,Babel對Gulp,Grunt和Webpack都有對應(yīng)的插件。
安裝Gulp插件示例:
$ npm install --save-dev gulp-babel
在gulpfile.js中,定義這么一個(gè)任務(wù),將src目錄下的app.js文件編譯到build目錄下:
var gulp = require('gulp'),
babel = require('gulp-babel')
gulp.task('build', function () {
return gulp.src('src/app.js')
.pipe(babel())
.pipe(gulp.dest('build'))
})
Node.js和ES6
對于Node.js,你可以用構(gòu)建工具或者直接用獨(dú)立模塊babel-core
:
$ npm install --save-dev babel-core
然后在Node.js中調(diào)用這個(gè)函數(shù):
require('babel-core').transform(es5Code, options)
ES6的一些總結(jié)
ES6中還有很多比較不錯(cuò)的特性,如:
Math / Number / String/ Array/ Object中新的方法
二進(jìn)制和八進(jìn)制數(shù)據(jù)類型
自動(dòng)展開多余參數(shù)
For of循環(huán)
Symbols
尾部調(diào)用優(yōu)化generator
更新的數(shù)據(jù)結(jié)構(gòu)(如Map和Set)
ES6相對于ES5的確是有比較大的優(yōu)化,必然是未來發(fā)展的趨勢所在,所以大家還是抓緊學(xué)習(xí)使用ES6吧。