20211028 # 函式 是物件的一種,通常一個函式會包含三個部分: - 函式的名稱 (也可沒有名稱) - 在括號 ( ) 中的部分,稱為「參數 (arguments) 」,參數與參數之間會用逗號 , 隔開 - 在大括號 { } 內的部分,內含需要重複執行的內容,是函式功能的主要區塊。 ### 參數 (Parameter) 可以透過「函式名稱」加上「小括號」的方式呼叫。 而小括號內的資料,就是「參數」。 **參數:在函式定義中所列出的變數** ```javascript= function plus(numA, numB) { let total =numA + numB; return total; }; plus(1, 2); // 3 plus(3); // NaN ``` 上方例子中,括號內的 numA、numB 就是 參數 :::info function 沒有參數也是能執行的 而在 JavaScript 裡,函式中的參數,預設值都是 **undefined** 也可以在一開始就給 **參數指定預設值** ::: ### 引數 (Arguments) **呼叫函式時,傳給該函式的參數的值** ```javascript= function show(a,b,c){ console.log(a,b,c); console.log(arguments); console.log(arguments[0]); console.log(arguments.length); console.log(typeof arguments); } show(1,2,3); ``` ![](https://i.imgur.com/qib15zq.png) :::info - arguments 儲存了所有傳遞參數的值。且還可以用length屬性 - 但**它並不是一個陣列**,是一個叫做**類陣列**的東西,也就是說無法使用 JS 提供給 array 的函式庫。 ::: ```javascript= function eatFood(fruit, vegetable) { console.log(arguments) console.log(arguments.length); }; eatFood('apple', 'cabbage') ``` ```javascript= //用在迴圈 const sum = function () { let num = 0; for (var i = 0; i < arguments.length; i++) { num += arguments[i]; } return num; }; sum(3, 4, 5); // 12 ``` ```javascript= // 抓出最大值 Max(1,5,100,20); // 100 function Max() { var max = 0; var num = arguments; // 把引數陣列丟進num // num.length → 4 // num[0] → 1 ; num[1] → 5; num[2] → 100... for (var i=0; i<num.length; i++) { if (max < num[i]) max = num[i]; // 當前元素大於max時,max更新 } return max; } ``` ### 以「物件」作為參數 將多個參數用一個「物件」包裝起來。 ```javascript= function card(Name, phone, email, address) { } card(); //'Woody', '0912345678', 'aa@gmail.com','Taipei' ``` 順序不能錯,參數不能漏,少了一個,位置就會錯 #### 改用「物件」的方式來取代這一堆參數 ```javascript= let card = { Name: 'Woody', phone: '0912345678', email: '0987654321', address: 'aa@gmail.com', address: 'Taipei' }; addPerson(card); ``` ### 參數的預設檢查 上面提到參數可以多,但少了就會"undefined" 避免出現NaN,可以改寫: ```javascript= function plus(numA, numB) { let total =(numA||0) + (numB||0); return total; }; plus(2,3); // 5 plus(99); //99 ``` # 閉包(Closure) - 閉包就是 Function 內的 Function(上面就是兩層function) - 閉包內層的變數記憶體不會被釋放,**可以被內層函式,不會被外面直接讀取** ```javascript= function foo() { var a = 2; function bar() { console.log(a); } return bar; } var baz = foo(); baz(); // 2 ``` ```javascript= function wait(message) { setTimeout(function() { console.log(message); }, 1000); } wait('hi, Closure!'); ``` 迴圈與閉包 ```javascript= for (var i = 0; i < 5; i++) { setTimeout(function() { console.log(i); }, i * 1000); } //5 5 5 5 5 //上面這段 code 執行的結果是 //單純的印出 i,但印的不是執行 setTimeout 時的 i,是執行 console.log(i) 時的 i; //所以當迴圈跑完時, i 的值會停在 5(迴圈終止),最後 才執行 console.log(i) 就會一直是 5。 // 建立立即函式 for (var i = 0; i < 5; i++) { (function(i) { setTimeout(function() { console.log(i); }, i * 1000); })(i); } //使用let for (let i = 0; i < 5; i++) { setTimeout(function() { console.log(i); }, i * 1000); } ``` setTimeout 語法 [MDN](https://developer.mozilla.org/zh-CN/docs/Web/API/setTimeout) ``` var timeoutID = scope.setTimeout(function[, delay, arg1, arg2, ...]); var timeoutID = scope.setTimeout(function[, delay]); var timeoutID = scope.setTimeout(code[, delay]); arg1, ..., argN 任選 附加參數,它們會作為參數傳遞function ``` ```javascript= for (var i = 0; i < 5; i++) { setTimeout(function(i) { console.log(i); }, i * 1000,i); } // ``` bind寫法我還不懂,待補充 ## 參考資料 1. [設計看JS - Parameter & Argument](https://ithelp.ithome.com.tw/articles/10240992) 2. [學JS的心路歷程 Day7-函式(二) arguments](https://ithelp.ithome.com.tw/articles/10204008) 3. [Javascript大全 - 06 函式(二) 參數、引數、閉包](https://yakimhsu.com/javascript/JS_Daquan-06_2.html) 4. [[JavaScript] 理解 JS中的arguments 與 parameters](https://dean34520.medium.com/%E7%90%86%E8%A7%A3-javascript%E4%B8%AD%E7%9A%84arguments-%E8%88%87-parameters-5028336976f6) 5. [[Day19] 參數(上)](https://ithelp.ithome.com.tw/articles/10277444) 6. [你懂 JavaScript 嗎?#15 閉包(Closure)](https://cythilya.github.io/2018/10/22/closure/) 7. [Tommy 老師帶你重新搞懂閉包 Closure](https://www.youtube.com/watch?v=ksmk5RO5DgU)