[讀書筆記]5個小技巧讓你寫出更好的JavaScript[圖]

在使用JavaScript時,咱們經常要寫很多的條件語句。這裏有五個小技巧,可讓你寫出更乾淨、漂亮的條件語句。
使用Array.includes來處理多重條件
舉個栗子:
//條件語句
functiontest(fruit){
if(fruit=='apple'||fruit=='strawberry'){
console.log('red');
}
}
乍一看,這麼寫彷佛沒什麼大問題。
然而,若是咱們想要匹配更多的紅色水果呢,比方說『櫻桃』和『蔓越莓』?咱們是否是得用更多的||來擴展這條語句?
咱們可使用Array.includes重寫以上條件句。
functiontest(fruit){
//把條件提取到數組中
constredFruits=['apple','strawberry','cherry','cranberries'];
if(redFruits.includes(fruit)){
console.log('red');
}
}
咱們把紅色的水果(條件)都提取到一個數組中,這使得咱們的代碼看起來更加整潔。
[讀書筆記]5個小技巧讓你寫出更好的JavaScript[圖]
少寫嵌套,儘早返回
讓咱們爲以前的例子添加兩個條件:
若是沒有提供水果,拋出錯誤;
若是該水果的數量大於10,將其打印出來。
functiontest(fruit,quantity){
constredFruits=['apple','strawberry','cherry','cranberries'];
//條件1:fruit必須有值
if(fruit){
//條件2:必須爲紅色
if(redFruits.includes(fruit)){
console.log('red');
//條件3:必須是大量存在
if(quantity>10){
console.log('bigquantity');
}
}
}else{
thrownewError('Nofruit!');
}
}
//測試結果
test(null);//報錯:Nofruits
test('apple');//打印:red
test('apple',20);//打印:red,bigquantity
讓咱們來仔細看看上面的代碼,咱們有:
1個if/else語句來篩選無效的條件;
3層if語句嵌套(條件1,2&3)。編程

JavaScript(簡稱「JS」) 是一種具備函數優先的輕量級,解釋型或即時編譯型的高級編程語言。雖然它是做爲開發Web頁面的腳本語言而出名的,讀書筆記https://www.yuananren.com可是它也被用到了不少非瀏覽器環境中,JavaScript 基於原型編程、多範式的動態腳本語言,而且支持面向對象、命令式和聲明式(如函數式編程)風格。
就我我的而言,我遵循的一個總的規則是當發現無效條件時儘早返回。

/當發現無效條件時儘早返回/
functiontest(fruit,quantity){
constredFruits=['apple','strawberry','cherry','cranberries'];
//條件1:儘早拋出錯誤
if(!fruit)thrownewError('Nofruit!');
//條件2:必須爲紅色
if(redFruits.includes(fruit)){
console.log('red');
//條件3:必須是大量存在
if(quantity>10){
console.log('bigquantity');
}
}
}
如此一來,咱們就少寫了一層嵌套。這是種很好的代碼風格,尤爲是在if語句很長的時候(試想一下,你得滾動到底部才能知道那兒還有個else語句,是否是有點不爽)。
若是反轉一下條件,咱們還能夠進一步地減小嵌套層級。注意觀察下面的條件2語句,看看是如何作到這點的:
/當發現無效條件時儘早返回/
functiontest(fruit,quantity){
constredFruits=['apple','strawberry','cherry','cranberries'];
if(!fruit)thrownewError('Nofruit!');//條件1:儘早拋出錯誤
if(!redFruits.includes(fruit))return;//條件2:當fruit不是紅色的時候,直接返回
console.log('red');
//條件3:必須是大量存在
if(quantity>10){
console.log('bigquantity');
}
}
經過反轉條件2的條件,如今咱們的代碼已經沒有嵌套了。
當咱們代碼的邏輯鏈很長,而且但願當某個條件不知足時再也不執行以後流程時,這個技巧會很好用。
然而,並無任何硬性規則要求你這麼作。這取決於你本身,對你而言,這個版本的代碼(沒有嵌套)是否要比以前那個版本(條件2有嵌套)的更好、可讀性更強?
是個人話,我會選擇前一個版本(條件2有嵌套)。緣由在於:
這樣的代碼比較簡短和直白,一個嵌套的if使得結構更加清晰;
條件反轉會致使更多的思考過程(增長認知負擔)。
所以,始終追求更少的嵌套,更早地返回,可是不要過分。
感興趣的話,這裏有篇關於這個問題的文章以及StackOverflow上的討論:
AvoidElse,ReturnEarlybyTimOxley
StackOverflowdiscussiononif/elsecodingstyle
使用函數默認參數和解構
我猜你也許很熟悉如下的代碼,在JavaScript中咱們常常須要檢查null/undefined並賦予默認值:
functiontest(fruit,quantity){
if(!fruit)return;
constq=quantity||1;//若是沒有提供quantity,默認爲1
console.log(Wehave${q}${fruit}!);
}
//測試結果
test('banana');//Wehave1banana!
test('apple',2);//Wehave2apple!
事實上,咱們能夠經過函數的默認參數來去掉變量q。
functiontest(fruit,quantity=1){//若是沒有提供quantity,默認爲1
if(!fruit)return;
console.log(Wehave${quantity}${fruit}!);
}
//測試結果
test('banana');//Wehave1banana!
test('apple',2);//Wehave2apple!
是否是更加簡單、直白了?
請注意,全部的函數參數均可以有其默認值。舉例來講,咱們一樣能夠爲fruit賦予一個默認值:
functiontest(fruit=‘unknown’,quantity=1)。
那麼若是fruit是一個對象(Object)呢?咱們還可使用默認參數嗎?
functiontest(fruit){
//若是有值,則打印出來
if(fruit&&fruit.name){
console.log(fruit.name);
}else{
console.log('unknown');
}
}
//測試結果
test(undefined);//unknown
test({});//unknown
test({name:'apple',color:'red'});//apple
觀察上面的例子,當水果名稱屬性存在時,咱們但願將其打印出來,不然打印『unknown』。
咱們能夠經過默認參數和解構賦值的方法來避免寫出fruit&&fruit.name這種條件。
//解構——只獲得name屬性
//默認參數爲空對象{}
functiontest({name}={}){
console.log(name||'unknown');
}
//測試結果
test(undefined);//unknown
test({});//unknown
test({name:'apple',color:'red'});//apple
既然咱們只須要fruit的name屬性,咱們可使用{name}來將其解構出來,以後咱們就能夠在代碼中使用name變量來取代fruit.name。
咱們還使用{}做爲其默認值。
若是咱們不這麼作的話,
在執行test(undefined)時,你會獲得一個錯誤Cannotdestructurepropertynameof‘undefined’or‘null’.,
由於undefined上並無name屬性。
(譯者注:這裏不太準確,其實由於解構只適用於對象(Object),而不是由於undefined上並無name屬性(空對象上也沒有)。參考解構賦值-MDN)
若是你不介意使用第三方庫的話,有一些方法能夠幫助減小空值(null)檢查:
使用Lodashget函數;
使用Facebook開源的idx庫(需搭配Babeljs)。
這裏有一個使用Lodash的例子:
//使用lodash庫提供的方法
functiontest(fruit){
//獲取屬性name的值,若是沒有,設爲默認值unknown
console.log(
.get(fruit,'name','unknown');
}
//測試結果
test(undefined);//unknown
test({});//unknown
test({name:'apple',color:'red'});//apple
你能夠在這裏運行演示代碼。
另外,若是你偏心函數式編程(FP),你能夠選擇使用Lodashfp——函數式版本的Lodash(方法名變爲get或getOr)。
相較於switch,Map/Object也許是更好的選擇
讓咱們看下面的例子,咱們想要根據顏色打印出各類水果:
functiontest(color){
//使用switchcase來找到對應顏色的水果
switch(color){
case'red':
return['apple','strawberry'];
case'yellow':
return['banana','pineapple'];
case'purple':
return['grape','plum'];
default:
return[];
}
}
//測試結果
test(null);//[]
test('yellow');//['banana','pineapple']
上面的代碼看上去並無錯,可是就我我的而言,它看上去很冗長。一樣的結果能夠經過對象字面量來實現,語法也更加簡潔:
//使用對象字面量來找到對應顏色的水果
constfruitColor={
red:['apple','strawberry'],
yellow:['banana','pineapple'],
purple:['grape','plum']
};
functiontest(color){
returnfruitColor[color]||[];
}
或者,你也可使用Map來實現一樣的效果:
//使用Map來找到對應顏色的水果
constfruitColor=newMap()
.set('red',['apple','strawberry'])
.set('yellow',['banana','pineapple'])
.set('purple',['grape','plum']);
functiontest(color){
returnfruitColor.get(color)||[];
}
Map是ES2015引入的新的對象類型,容許你存放鍵值對。
那是否是說咱們應該禁止使用switch語句?別把本身限制住。
我本身會在任何可能的時候使用對象字面量,可是這並非說我就不用switch,這得視場景而定。
ToddMotto有一篇文章深刻討論了switch語句和對象字面量,你也許會想看看。
懶人版:重構語法
就以上的例子,事實上咱們能夠經過重構咱們的代碼,使用Array.filter實現一樣的效果。
constfruits=[
{name:'apple',color:'red'},
{name:'strawberry',color:'red'},
{name:'banana',color:'yellow'},
{name:'pineapple',color:'yellow'},
{name:'grape',color:'purple'},
{name:'plum',color:'purple'}
];
functiontest(color){
//使用Arrayfilter來找到對應顏色的水果
returnfruits.filter(f=>f.color==color);
}
解決問題的方法永遠不僅一種。對於這個例子咱們展現了四種實現方法。
Codingisfun!
使用Array.every和Array.some來處理所有/部分知足條件
最後一個小技巧更多地是關於使用新的(也不是很新了)JavaScript數組函數來減小代碼行數。
觀察如下的代碼,咱們想要檢查是否全部的水果都是紅色的:
constfruits=[
{name:'apple',color:'red'},
{name:'banana',color:'yellow'},
{name:'grape',color:'purple'}
];
functiontest(){
letisAllRed=true;
//條件:全部的水果都必須是紅色
for(letfoffruits){
if(!isAllRed)break;
isAllRed=(f.color=='red');
}
console.log(isAllRed);//false
}
這段代碼也太長了!咱們能夠經過Array.every來縮減代碼
constfruits=[
{name:'apple',color:'red'},
{name:'banana',color:'yellow'},
{name:'grape',color:'purple'}
];
functiontest(){
//條件:(簡短形式)全部的水果都必須是紅色
constisAllRed=fruits.every(f=>f.color=='red');
console.log(isAllRed);//false
}
清晰多了對吧?
相似的,若是咱們想要檢查是否有至少一個水果是紅色的,咱們可使用Array.some僅用一行代碼就實現出來。
constfruits=[
{name:'apple',color:'red'},
{name:'banana',color:'yellow'},
{name:'grape',color:'purple'}
];
functiontest(){
//條件:至少一個水果是紅色的
constisAnyRed=fruits.some(f=>f.color=='red');
console.log(isAnyRed);//true
}
讓咱們一塊兒寫出可讀性更高的代碼吧。但願這篇文章能給大家帶來一些幫助。就是這樣啦~Happycoding!數組

相關文章
相關標籤/搜索