讓初學者能更優美編撰 JavaScript 的小撇步
「我要努力向上,不付諸君期望」
整人專家-胡真
就前端初學者的思維,大多會把「寫出可以運行的 code 」當作是練習或是實作的終極目標,而美化 code 內容或是使其運行效率更快什麼的,等到實力累積到一定程度之後在來處理就好。(好吧也有可能只有我是這樣想 QQ )
但其實世界是美好的~有些優化的關鍵其實只是透過一些基礎概念的運用便可達成,不需要多艱深的知識就能使用自如,本篇就以 JavaScript 中常會使用的判斷式與迴圈為例,透過一些使用上的小訣竅讓 code 更加美化~
一. if 與 switch 的使用時機
身為 JavaScript 判斷式的兩本柱,switch 真的是存在感渺小的可憐,因為 if 的自由度跟彈性真的是比 switch 來得強大許多,但其實 switch 也沒那麼不堪,有些時候派他上場反而能使 code 更加美觀而且不會妨礙運行效力喔!
舉個例子,當今天有一個欄位要請使用者填入 1~n,然後依照填入的各種數字有對應的功效,使用 if 的話應該會寫成:
var input_number = 輸入數字
if(input_number === '1'){
console.log('子瑜我婆');
}else if(input_number === '2'){
console.log('初音我婆');
}else if(input_number === '3'){
......
......
}else{
console.log('全都是我婆');
}
當填入的數字越多,要鍵入的 input_number 次數就越多,雖然有複製貼上但也是挺麻煩的,而且畫面也因為夾雜許多不同種類的括弧而有些雜亂,此時只要使用被遺忘的 switch :
var input_number = 輸入數字
switch(input_number){
case '1':
console.log('子瑜我婆');
break;
case '2':
console.log('初音我婆');
break;
......
......
default:
console.log('全都是我婆');
}
比較一下兩邊的內容,switch 版本是不是比較漂亮一些呢~這邊補充一個微知識,switch 是使用全等模式判斷(就是 if 中的三個等號),所以在上面的範例,千萬不能寫成 case 1: 這樣,不然就會直接走 default 分支喔!
二. 三目運算子(三元運算子/條件運算子)
相信有不少新手在自學時,上網拜讀各個大神的文章時,時常會看到 code 中判斷式夾雜著 ? 與 : 的語句,看到的當下肯定是滿腦子問號,其實這就是大名鼎鼎的三目運算子,公式如下:
//使用 if 判斷式
if(target){
//當目標為 True 時的答案
}else{
//當目標為 False 時的答案
}
//使用三目運算子
(target) ? (//當目標為 True 時的答案) : (//當目標為 False 時的答案)
上面可以看到,使用三目運算子可以將五行的 code 縮減成一行結束,真的簡單有力又省時~以下舉幾個例子:
//如果考試前有拜春哥及關帝則可上榜,否則落榜
拜春哥||拜關帝 ? 上榜 : 落榜;
//三目運算子也可以運用到 jquery 上
//當 target 為 True 時使用 addClass 方法,False 時則使用 removeClass
target ? $('body').addClass('子瑜') : $('body').removeClass('子瑜');
//將上面的 code 昇華一下
$('body')[target ? 'addClass' : 'removeClass']('子瑜');
//套用在function上
function a(){....}
function b(){....}
target ? a() : b();
三. return 的美妙之處
在判斷式中,return 常用來返回達成目標對應之值,但其實 return 同時也會終止函式的執行,活用 return 則可以減少 if else 的使用,使 code 更加美觀,像是下面的例子:
//當搜尋欄按下enter時才會進行動作,當搜尋欄為空值則 alert('欄位不得空白')
//一般寫法
searchbar.addEventListener('keyup', function(e){
if(e.keyCode === '13'){
if(this.value === ''){
alert('欄位不得空白');
}else{
//搜尋動作
}
}
}
//活用return的寫法
searchbar.addEventListener('keyup', function(e){
if(!e.keyCode === '13'){
return;
}
if(this.value === ''){
alert('欄位不得空白');
return;
}
//搜尋動作
}
//更簡潔的寫法
searchbar.addEventListener('keyup', function(e){
if(!e.keyCode === '13') return;
if(this.value === '') return alert('欄位不得空白');
//搜尋動作
}
上面的例子可以看出使用 return 可以減少巢狀的寫法,使 code 簡潔有力,真的是個神奇的小東西~
四. for 陳述式/for in/forEach/for of 的效能比較
講完了判斷式的優化撇步,也來談談迴圈吧!迴圈最常被用到的就是 for-loop 了,而 for 迴圈也有百百中,各種都有不同的美妙跟運行能力,關於這些用法執行的效率測試估狗大神已經滿多都有實作的,本篇就直接破題統整各種 for-loop 的效能與用途(想看效能實測的人可以看這篇)
- for 陳述式 : 效能最高,其實一般使用都建議用此方法,但寫法有些繁瑣(參考連結)
- for in : 效能最低(需要歷遍對象的所有屬性),運行耗時最久,類似 forEach 但可作用在 object 跟 array 上(參考連結)
- forEach : 效能一般,目標為 array 時推薦使用,寫法簡單清楚速度又不算慢( 參考連結)
- for of : 效能中上(略高於 forEach),屬於 ES6 的語法,其寫法簡潔有力,兼具 for in 的優點又避開其所有缺陷,與 forEach 不同的是,此語法可響應 break、return、continue 等語句(參考連結)
五. 讓 for-loop 更加有效率吧!
除了透過活用上面各種 for-loop 的語法外,也可以透過一些小技巧來使迴圈運行更有效率喔!
1. 減少迭代的工作量
我們拿兩個例子來做比較
//Case A
for(var i = 0; i < target.length; i++){
//迭代內容;
}
//Case B
for(var i = 0,len = target.length; i < len; i++){
//迭代內容;
}
上面兩個案例都可以達到相同的目標,但 CaseA 每迭代一次就需要計算一次 target 的長度,累加下來會比 CaseB 耗費更多的時間,所以如果迴圈中有已知的參數,盡量在迴圈外就將其定義,則可減少迴圈迭代的工作量。
這邊補充一個微知識,如果無關迭代的運算也別放在迴圈內喔,不然也會增加迴圈工作量(雖然能減少 code 的行數,好像是有達到美觀效果)。
2. 降低迭代的次數
就算是一個再有效率的 code ,當迭代次數過多時,還是會受其影響而使 運行效能降低,如果能在迴圈中使用展開技術,減少迭代的次數,就可以提高效能。上面的敘述相信很多人看到都會有所共鳴,沒錯!這就是傳說中的廚具,阿不是,是傳說中的達夫裝置(關於達夫裝置的定義可以看wiki),簡單來說達夫裝置是一個迴圈體展開技術,使得一次迭代實際執行了多次迭代的操作,最初是用在 C 語言中,後面則出現 JavaScript 的應用版本,其 code 如下:
var iterations = Math.floor(items.length/8),
startAt = items.length%8,
i = 0;
do{
switch(startAt){
case 0 : process(items[i++]);
case 7 : process(items[i++]);
case 6 : process(items[i++]);
case 5 : process(items[i++]);
case 4 : process(items[i++]);
case 3 : process(items[i++]);
case 2 : process(items[i++]);
case 1 : process(items[i++]);
}
startAt = 0;
}while(--iterations);
但根據網路大大們實測,當迭代量少時,使用達夫裝置反而會適得其反,所以使用上還需自行評估喔>Q^
六. 迴圈中的邊緣人- while
判斷式有其邊緣人 switch,迴圈當然也有!就是 while-loop~~
while-loop 使用上與 for-loop 用途一樣,用來重覆執行 while(for) 區塊內的語句,但是,就是這個但是,使用 while-loop 時,如果一不小心忘記給他一個計算值,使其有辦法跳出迴圈,就很容易產生可怕的無限循環~再加上使用上的美觀程度跟效能也不會比 for 迴圈來得高,所以活該被遺忘較少人使用。
但是其實 while 迴圈有一個鮮為人知的用法,就是 do...while 迴圈,它的語法如下:
do {
//欲進行的動作
} while (判斷目標);
這個方法與一般的 while-loop 類似,比較特別的是他會先執行一次動作才開始判斷,當遇到需要先執行後判斷的狀況時,就可以活用 do...while 迴圈達到目的,並且能讓 while-loop 增加就業機會~真滴佛心!
以上就是本篇彙整個幾個優化小撇步,之後如果有遇到或學到更多撇步再來補充囉~上述內容如果有任何問題煩請告知,小弟會立即修正!!!也希望如果有其他優化的小技巧,大家能不吝分享~~讓世界更加美好!