JS 基本概念大補帖(下)
你是否和我一樣快速入手 JS 時沒想太多,但到頭來才發現少了些什麼呢?
那麼~這篇文章就是為你而寫
以下為 JS 五問下集,送給同是新手的你們 🙌 如果還沒看上集的人先去看完再回來吧!
🎯 什麼是迴圈?
所謂迴圈就是一個永無止盡的迭代循環,簡單來說就是當滿足一定條件的情況下程式碼會自動幫你一次又一次的執行,直到達到另一個條件/限制(或是系統 crashdown 😱)才會停止
常見的迴圈有兩種:For & While
For 迴圈:
1. 寫法🖊:
與 Python 寫法略微不同,JS 的 for 迴圈的表法為:
for ( var i=0; i<7; i++) { // 當 i<7 時執行花括號內程式碼 }
🔺 注意:
a. for 後擺 3 個值:第一個為初始化變數(觀察值)、第二個為預設需滿足的條件、第三個為觀察值的變化/迭代
b. 每個值之間都需要加上分號(;)區隔
2. 時機
用於「可預期執行次數」的迴圈
While 迴圈
1. 寫法🖊:
while(condition) { // 當條件成立 (True) 時會重複執行花括號內的程式碼 } var i = 0; while(i<7) { console.log(i) }
🔺 注意:
a. 條件式必須為布林值 (boolean),使 while 能夠判斷 True/False
b. 條件式需定義非常嚴謹,否則會出現上述的系統當機的情況
2. 時機
用於「不確定次數」的迴圈
🎯 為什麼要有函式 (function)? 如何宣告函式 (Function Declaration) ?
函式會存在是出自於人類的惰性。說好聽些,函式的功能為建立一套 SOP(流程), 將常用的功能寫成函式,方便需要特定功能時立即(重複)取用
函式宣告語法🖊:
function functionName(parameter1, parameter2,…) {
// 當函式被呼叫時會執行的程式碼
}
🔺 注意:
- 於小括號 () 中放入指定參數,參數如果超過一項需用逗號隔開
- 函式花括號中的程式碼可加入回傳資料功能,只需要加入 return 關鍵字即可
- 函式中若無參數,仍然需有小括號
- 函式命名上記得避開保留字,並注意大小寫
宣告完函式,接著需要時就會需要「呼叫函式 (Function Invocation)」
呼叫函式的方法有 2 種:
- 先返回到一個變數中 Ex: var
- 可直接由其他 JavaScript 程式碼主動呼叫 Ex: console.log() 輸出函式值
- 或由 HTML 事件觸發 Ex: onclick
- 若函式外加上兩組小括號(如下兩種寫法),即可將一般函式宣告轉為「立即函式 (self-invoking expression)」或稱 IIFE (Immediately Invoked Function Expression),做一次性、立即性的呼叫,且該函式不需另外命名(故也為匿名函式的一種)。
(function () { … })()
(function () { … }())
📎補:IIFE 中的變數為「區域變數」,不會影響或污染全域的變數設定!有一句話可以銘記:減少「全域變數」的產生,就是避免了變數名稱的衝突(大亂)。
🔺 注意:
- 函式可在 HTML 的 head 或 body 中被呼叫
- 函式在呼叫時
🎯 函式宣告式?函式表達式?
身為 JS 學員的你們應該對於「函式宣告式 (function declaration/ statement)」和「函式表達式 (function expression)」這兩個名詞不陌生,但是兩者究竟差在哪呢?
讓我們來看看以下例子:
// Function declaration function add(num1, num2) { return num1 * num2; }
// Function expression var add = function (num1, num2) { return num1 * num2; };
如果稍微喵到以下函式建立種類的人應該會覺得上述的宣告、表達式有點眼熟👀~ 沒有錯!「函式宣告式 」就是我們理解的「一般函式宣告」法;而「函式表達式」同時涵蓋了「匿名&具名函式運算式」
🥤 功能上,兩者最大的差異為:
函式宣告式在執行程式的起始,該函式就會優先被儲存在記憶體中,同時優先被執行。不管寫在前或後都不會有差異( JS Hoisting 原理)
函式表達式是將函式儲存在變數中(🔑 別忘了 function 也是 object 唷!),因此在 var 當中的函式層級會被當作變數,自然而然就無法獲得優先轉譯權~
例子見以下👇
函式宣告式
hola(); // 印出 “Buenos dias” function hola() { console.log(“Buenos dias”); }
函式表達式
hola(); // Uncaught SyntaxError: Invalid or unexpected token ;使用「函式表達式」不能在定義前呼叫 var hola = function() { console.log(“Buenos dias”); };
🎯 建立函式的方法有哪些?
函式建立上有常見的 4 種方式:
- 一般函式宣告: function irisFunction() { }
- 匿名函式運算式:var irisFunction = function() { }
- 具名函式運算式:var irisFunction = function(functionName) { }
- 函式關鍵字定義:var irisFunction = new function()
🔑 會有這麼多定義函式的方式出現,背後想必有一些差異在吧? 沒錯!
舉例來說:
- 使用「一般函式宣告」的優點為不需過度在意 hoisting 的順序問題
- 具名函式在錯誤顯示上較為方便,系統會直接報出該函式名字,以便 debug
- 函式中可再寫入函式,但不宜再寫入「以關鍵字定義」的函式
🎯 你聽過「閉包 (closure)」嗎? 如果有,恭喜你比我資深嘍!
小白我前一些日子才聽過閉包這個神奇的名詞,聽到的當下可說是完全沒想法、不知道函式中還能關閉些什麼、包裝些什麼,直到我上網爬了無數資料,才讓我這個理解能力低落的程式小白搞懂,今天就讓我一次跟你們用白話文說明白吧!
首先,我們都知道函式中的變數為 function scope,也就是只要一個變數被禁錮在函式之中,它就出不去了、外界沒有辦法和它聯絡,奇怪的是,它卻有辦法接收到外面世界的資訊。
了解 function scope 的特性後,你們應該就不難想像什麼是 global scope。沒有錯,global scope 就是相對於 function scope 的全局變數。凡是生長在函式之外空間的變數,都落在 global scope 範疇。誠如剛剛所述,global scope 的變數無法洞見孤立在小閣樓的 function scope 變數在做的事,也就是無法得知 function scope 變數的值。
但這時,好心的我們就會想… 要怎麼拯救困在 function scope 的變數呢?難道它的命運就是如此,就註定坎坷嗎?真的沒有轉機了嗎?
針對這個命運攸關的問題,工程師給出折衷的解決方案,你們可以聽看看。
工程師曰:「在 function 中建立另一個 function,然後 return 回去呀!」
小白:「哪泥!? 咁安捏?」
於是乎,小白哭著回家找谷爺爺(全名:谷歌)。爺爺啥都沒說給了小白一張卡帶。小白無精打采地把卡帶拎回房間,默默坐到房角一隅,隨手將卡帶插進卡夾,美妙的噪音開始播放🎼
聽完一曲,小白彷彿醍醐灌頂(職業病犯,馬上接入重點!)
馬上來看看小白聽到了些什麼~
🔺註:以下為改編,因曲子有版權無法擅自使用
function listenToIrisSong () { var musicalNote = Math.random(); function genMusicalNote () { return musicalNote; } return genMusicalNote; } var melodyFirstSection = listenToIrisSong(); var melodySecondSection = listenToIrisSong(); console.log(melodyFirstSection()); console.log(melodySecondSection());
相信大家對 return 功能並不陌生,return 的作用即是終止當前運行的函式,並從該函式返回一個值。那既然大家懂 return,也懂函式,不妨思考看看:以上曲子為什麼要由兩個函式構成呢?(給你們3秒鐘思考~)
3
2
1
時間到!
以上的雙層函式寫法是為了將函式內的私人變數值 musicalNote 能夠被函式外接收,也就是意在「拯救困在閣樓的 function scope 變數」。藉由返回(return)genMusicalNote 內層函式到 global scope,將函式能被外層取用。
另一方面,一個函式需要保有個人存儲的私有變數,而不需被外部揭露,就像是出門前需要做的 SOP 不需告知朋友你的出門清單,才能踏出家門。因此,為了更完整保存變數和資料,我們會使用閉包的雙層結構加強保存。
那為什麼不用單層函式再 return 就好了呢? 因為這樣的操作已經被寫死(無法另做調整),換句話說,單層結構無法達到我們想到的溝通、保存效果。
如果還有什麼問題,歡迎以下留言區提出!也非常歡迎加入程式小白一起和 JS 初學者一起發問討論唷!
Reference 參考資料:
- https://medium.com/@miahsuwork/%E7%AC%AC%E5%9B%9B%E9%80%B1-javascript-%E5%87%BD%E5%BC%8F-function-5c6114de5fff
- https://ithelp.ithome.com.tw/articles/10203027
- https://www.fooish.com/javascript/function.html
- https://ithelp.ithome.com.tw/articles/10208709
- https://pjchender.blogspot.com/2016/03/javascriptfunction-statements-and.html
- https://eyesofkids.gitbooks.io/javascript-start-from-es6/content/part3/function_scope.html
- https://ithelp.ithome.com.tw/articles/10192739
- https://pjchender.blogspot.com/2016/03/javascriptfunction-statements-and.html
- https://wcc723.github.io/javascript/2017/12/13/javascript-closure/