大家知道,將ES6代碼編譯為ES5時(shí),我們常用到Babel這個(gè)編譯工具胞四。大家參考一些網(wǎng)上的文章或者官方文檔刚操,里面常會(huì)建議大家在.babelrc中輸入如下代碼:
{
"presets": [
"es2015",
"react",
"stage-0"
],
"plugins": []
}
我們現(xiàn)在來說明下這個(gè)配置文件是什么意思闸翅。首先,這個(gè)配置文件是針對(duì)babel 6的菊霜。Babel 6做了一系列模塊化坚冀,不像Babel 5一樣把所有的內(nèi)容都加載。比如需要編譯ES6鉴逞,我們需要設(shè)置presets為"es2015"记某,也就是預(yù)先加載es6編譯的相關(guān)模塊,如果需要編譯jsx构捡,需要預(yù)先加載"react"這個(gè)模塊液南。那問題來了,這個(gè)"stage-0"又代表什么呢勾徽? 有了"react-0"滑凉,是否又有諸如"stage-1", "stage-2"等等呢?
事實(shí)上, ”stage-0"是對(duì)ES7一些提案的支持畅姊,Babel通過插件的方式引入闪幽,讓Babel可以編譯ES7代碼。當(dāng)然由于ES7沒有定下來涡匀,所以這些功能隨時(shí)肯能被廢棄掉的《㈦纾現(xiàn)在我們來一一分析里面都有什么。
1. 法力無邊的stage-0
為什么說“stage-0” 法力無邊呢陨瘩,因?yàn)樗瑂tage-1, stage-2以及stage-3的所有功能腕够,同時(shí)還另外支持如下兩個(gè)功能插件:
transform-do-expressions
transform-function-bind
用過React的同學(xué)可能知道,jsx對(duì)條件表達(dá)式支持的不是太好舌劳,你不能很方便的使用if/else表達(dá)式帚湘,要么你使用三元表達(dá),要么用函數(shù)甚淡。例如你不能寫如下的代碼:
var App = React.createClass({
render(){
let { color } = this.props;
return (
<div className="parents">
{
if(color == 'blue') {
<BlueComponent/>;
}else if(color == 'red') {
<RedComponent/>;
}else {
<GreenComponent/>; }
}
}
</div>
)
}
})
在React中你只能寫成這樣:
var App = React.createClass({
render(){
let { color } = this.props;
const getColoredComponent = color => {
if(color === 'blue') { return <BlueComponent/>; }
if(color === 'red') { return <RedComponent/>; }
if(color === 'green') { return <GreenComponent/>; }
}
return (
<div className="parents">
{ getColoredComponent(color) }
</div>
)
}
})
transform-do-expressions 這個(gè)插件就是為了方便在 jsx寫if/else表達(dá)式而提出的大诸,我們可以重寫下代碼。
var App = React.createClass({
render(){
let { color } = this.props;
return (
<div className="parents">
{do {
if(color == 'blue') {
<BlueComponent/>;
}else if(color == 'red') {
<RedComponent/>;
}else {
<GreenComponent/>; }
}
}}
</div>
)
}
})
再說說 transform-function-bind, 這個(gè)插件其實(shí)就是提供過 :: 這個(gè)操作符來方便快速切換上下文贯卦, 如下面的代碼:
obj::func
// is equivalent to:
func.bind(obj)
obj::func(val)
// is equivalent to:
func.call(obj, val)
::obj.func(val)
// is equivalent to:
func.call(obj, val)
// 再來一個(gè)復(fù)雜點(diǎn)的樣例
const box = {
weight: 2,
getWeight() { return this.weight; },
};
const { getWeight } = box;
console.log(box.getWeight()); // prints '2'
const bigBox = { weight: 10 };
console.log(bigBox::getWeight()); // prints '10'
// Can be chained:
function add(val) { return this + val; }
console.log(bigBox::getWeight()::add(5)); // prints '15'
如果想更屌點(diǎn)资柔,還可以寫出更牛逼的代碼:
const { map, filter } = Array.prototype;
let sslUrls = document.querySelectorAll('a')
::map(node => node.href)
::filter(href => href.substring(0, 5) === 'https');
console.log(sslUrls);
2. 包羅萬象的stage-1
stage-1除了包含stage-2和stage-3,還包含了下面4個(gè)插件:
transform-class-constructor-call(Deprecated)
transform-class-properties
transform-decorators – disabled pending proposal update
transform-export-extensions
深藏不露的stage-2
為什么說 stage-2深藏不露呢撵割,因?yàn)樗艿驼{(diào)贿堰,低調(diào)到你可以忽略它,但事實(shí)上啡彬,它很有內(nèi)涵的羹与。它除了覆蓋stage-3的所有功能,還支持如下兩個(gè)插件:
syntax-trailing-function-commas
transform-object-reset-spread
syntax-trailing-function-commas
這個(gè)插件讓人一看覺得挺沒趣的庶灿,讓人甚至覺得它有點(diǎn)雞肋纵搁。因它不是對(duì)ES6功能的增加,而是為了增強(qiáng)代碼的可讀性和可修改性而提出的往踢。如下面的代碼所示:
// 假設(shè)有如下的一個(gè)函數(shù)腾誉,它有兩個(gè)參數(shù)
function clownPuppiesEverywhere(
param1,
param2
) { /* ... */ }
clownPuppiesEverywhere(
'foo',
'bar'
);
// 有一天,它需要變成3個(gè)參數(shù)菲语,你需要這樣修改
function clownPuppiesEverywhere(
param1,
- param2
+ param2, // 這一行得加一個(gè)逗號(hào)
+ param3 // 增加參數(shù)param3
) { /* ... */ }
clownPuppiesEverywhere(
'foo',
- 'bar'
+ 'bar', // 這里的修改為逗號(hào)
+ 'baz' // 增加新的參數(shù)
);
// 看到?jīng)]妄辩? 我們修改了4行代碼。山上。啊啊眼耀。修改了4行代碼。
修改了4行代碼佩憾,嗯嗯嗯哮伟。干花。追求高效的程序猿想想了,以后如果有更多參數(shù)了楞黄,我是不是要改等多行池凄,得想想,代碼改的越少越好鬼廓,于是有了下面的改動(dòng)肿仑。。
// 我們來重新定義一下函數(shù)
function clownPuppiesEverywhere(
param1,
param2, // 注意這里碎税,我們加了一個(gè)逗號(hào)喲
) { /* ... */ }
clownPuppiesEverywhere(
'foo',
'bar', // 這里我們也加了一個(gè)逗號(hào)
);
// 現(xiàn)在函數(shù)需要三個(gè)參數(shù)尤慰,我們來修改下
function clownPuppiesEverywhere(
param1,
param2,
+ param3, // 增加params3參數(shù)
) { /* ... */ }
clownPuppiesEverywhere(
'foo',
'bar',
+ 'baz', // 增加第三個(gè)參數(shù)
);
// 叮叮當(dāng),我們只修改了兩行代碼就完成了雷蹂,好開森
說實(shí)話吧伟端,這個(gè)功能讓人有點(diǎn)很無語。不過程序猿對(duì)干凈代碼的追求真的很讓人感動(dòng)匪煌,還是值得鼓勵(lì)的责蝠。這個(gè)就是stage-2中"尾逗號(hào)函數(shù)”功能。哈哈哈哈萎庭。
transform-object-rest-spread
再來說transform-object-rest-spread霜医, 其實(shí)它是對(duì) ES6中解構(gòu)賦值的一個(gè)擴(kuò)展摩骨,因?yàn)镋S6只支持對(duì)數(shù)組的解構(gòu)賦值玛荞,對(duì)對(duì)象是不支持的。如下面的代碼所示:
// 獲取剩下的屬性
let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };
console.log(x); // 1
console.log(y); // 2
console.log(z); // { a: 3, b: 4 }
// 屬性展開
let n = { x, y, ...z };
console.log(n); // { x: 1, y: 2, a: 3, b: 4 }
大放異彩的stage3
為啥說stage3大放異彩呢?因?yàn)樗С执竺ΧΦ腶sync和await, 這兩個(gè)哥們可是解決(Ajax)回調(diào)函數(shù)的終極解決方法呀达舒!管你什么異步,我都可以用同步的思維來寫叹侄,ES7里面非常強(qiáng)悍的存在巩搏。總的來說趾代,它包含如下兩個(gè)插件:
transform-async-to-generator
transform-exponentiation-operator
transform-async-to-generator
transform-async-to-generator主要用來支持ES7中的async和await贯底, 我們可以寫出下面的代碼:
const sleep = (timeout)=>{
return new Promise( (resolve, reject)=>{
setTimeout(resolve, timeout)
})
}
(async ()=>{
console.time("async");
await sleep(3000);
console.timeEnd("async");
})()
再來一個(gè)實(shí)際點(diǎn)的例子
const fetchUsers = (user)=>{
return window.fetch(`https://api.douban.com/v2/user/${user}`).then( res=>res.json())
}
const getUser = async (user) =>{
let users = await fetchUsers(user);
console.log( users);
}
console.log( getUser("flyingzl"))
提示: 由于asycn和await是ES7里面的內(nèi)容,現(xiàn)階段不建議使用撒强。為了順利運(yùn)行上面的代碼禽捆,建議用webpack進(jìn)行編譯。
transform-exponentiation-operator
transform-exponentiation-operator這個(gè)插件算是一個(gè)語法糖飘哨,可以通過**這個(gè)符號(hào)來進(jìn)行冪操作胚想,想當(dāng)于Math.pow(a,b)。如下面的樣例
// x ** y
let squared = 2 ** 2;
// 相當(dāng)于: 2 * 2
let cubed = 2 ** 3;
// 相當(dāng)于: 2 * 2 * 2
// x **= y
let a = 2;
a **= 2;
// 相當(dāng)于: a = a * a;
let b = 3;
b **= 3;
// 相當(dāng)于: b = b * b * b;
很簡(jiǎn)單也很實(shí)用吧芽隆,哈浊服。使用起來還是蠻方便的统屈。
總結(jié)
通過以上的兩篇文章,我們了解了stage-0,state-1牙躺,stage-2以及stage-3的區(qū)別愁憔。在進(jìn)行實(shí)際開發(fā)時(shí),可以更具需要來設(shè)置對(duì)應(yīng)的stage孽拷。如果省事懶得折騰吨掌,一般設(shè)置為stage-0即可。如果為了防止開發(fā)人員使用某些太新的功能脓恕,我們可以限制到某個(gè)特定的stage即可思犁。如果有其他問題,歡迎大家留言 :-)进肯。 更詳細(xì)的請(qǐng)參考https://babeljs.io/docs/plugins/preset-stage-0/