---
title: 'JS 核心 16 - 函式參數'
tags: JS 核心 ,JS , JavaScript, 函式參數
description: 2021/02/13
---
JS 核心 -- 函式參數
===
## 函式在運行時會帶入的變數
```
var globalVariable = '全域變數'; // 定義了全域變數
var obj = { // 在此物件下,定義了另一段函式
aFunction: function(para) { // 帶入三個參數,只取其中一個參數
var localVariables = '區域變數'; // 定義的區域變數
console.log(para, localVariables, arguments, this, globalVariable);
}
}
obj.aFunction('一段描述', 2, 3); // 執行物件內的函式,同時也有帶參數進來
```
* para : 傳入的參數。外層傳入三個參數,但函式內層只會接收第一個參數。
* localVariables : 在 aFunction 環境下定義的區域變數。
* arguments : 是一個類陣列。無論傳入多少參數,都可全部接收。
* this : 執行函式時會自動帶入的變數。執行物件內函式的 this 會與一般函式有所不同。
* globalVariable : 全域變數。
* 並非來自於函式本身,是來自於外層的變數。
* 在函式內無法取得此變數,所以函式會向外層尋找,並找到此變數為止。
* 可參考[範圍鏈章節](https://hackmd.io/U0vADI2zR76UYnGXMaklAQ)。

### :pencil2: **範例**
```
function callName(a) { // 在傳入參數時已定義好值了,變數 a 已存在
console.log(a); // 小明
var a; // 宣告一個變數時,若此變數已經存在,則重複宣告是無作用的
console.log(a); // 小明
a = '杰倫'; // 若要改變 a 的值,要使用重新賦予值的方式覆蓋掉
console.log(a); // 杰倫
}
callName('小明')
```
## 函式的陳述式 在執行 hositing 時,會把整個代碼移到最前方
```
function callName(a) { // 在傳入參數時已定義好值了,變數 a 已存在
console.log(a); // 小明
function a() {} // 定義一個函式陳述式
var a; // 宣告一個變數時,若此變數已經存在,則重複宣告是無作用的
console.log(a); // 小明
a = '杰倫'; // 若要改變 a 的值,要使用重新賦予值的方式覆蓋掉
console.log(a); // 杰倫
}
callName('小明')
```
執行結果為變數 a 被函式陳述式所取代了。
函式陳述式 function a( ){ } 移到 console.log(a); 之前,但不會比參數更前方。
> <span class="red">**變數 a 在參數一傳入時就已定義好了,hositing 不會影響變數 a 的值。**</span>
```
function callName(a) { // 在傳入參數時已定義好值了,變數 a 已存在
function a(){}; // 函式陳述式 hositing 移到前方,變數 a 被函式陳述式取代
console.log(a); // ƒ a(){}
var a;
console.log(a); // ƒ a(){}
a = '杰倫';
console.log(a); // 杰倫
}
callName('小明')
```
## 參數名稱可以自己定義
1. <span class="red">**參數名稱和傳入的值沒有關聯性**</span>
2. 只重視參數有幾個值、順序是怎樣...,不會受到外層的名稱所影響
3. 若傳入的參數數量不足,會在後方補上 undefined ( 如同變數未給值,也是呈現 undefined )
```
function callMore(d, c, b, a) {
console.log(d, c, b, a);
}
var a = 'a';
var b = 'b';
var c = 'c';
callMore(a, b, c); // a b c undefined
```
## 若參數是物件,有傳參考的特性
> 物件透過參數傳遞,也會維持傳參考的特性
> 很多程式碼規範都會建議不要去調整裡面的屬性參數,會導致原有的物件屬性被作調整
```
function callObject(obj) {
obj.name = '杰倫家'; // 修改物件內的屬性值
}
var family = {
name: '小明家'
}
callObject(family); // 執行 callObject 函式時,把物件傳進去
console.log(family); // {name: '杰倫家'}
```
## 回呼函式 Callback Function
* 把函式當作另一個函式的參數,透過另一個函式來呼叫它
* 這個函式只會在滿足了某個條件才會被動的去執行
* 定義一段函式,並把函式傳進來
### 函式直接寫在參數內
> fn 是在 functinoB 內建立的一個參數,在這邊是要說明函式傳入的參數也可以是一個 function,並且在函式中呼叫傳入函式,而這也就是所謂的 callback function。
1. functinoB 執行時將函式作為參數傳入 fn,並在 functinoB 內執行。
2. fn 的小明做為參數傳遞給 functinoB 執行時的函式。
```
function functionB(fn) { // 直接意義一段函式,並透過參數把函式傳進來
fn('小明'); // 裡面執行的此段函式,會把參數傳遞到外層來
}
functionB(function(a){console.log(a)}) // 小明
// 執行這段函式時就可帶入另一段函式 (可以是匿名的)
```
### 預先把函式定義好
1. 直接把 callSomeone 函式帶入,等同說執行另外一段表達式。
2. 把 callSomeone 函式賦予到 fn 變數上,所以 callSomeone 函式不用帶參數。
3. 首先在這邊函式 callSomeone 被當作參數傳入到 functionB,所以 functionB 的 fn 其實就是 callSomeone 的參數。
4. 直接在 functionB 中使用 fn ( ) 呼叫並傳入參數執行 functionB。
```
function callSomeone(name, a){ // 預先定義好另一段函式
console.log(name + '你好', a)
}
function functionB(fn) { // 直接定義一段函式,並透過參數把函式傳進來
fn('小明', 1); // 實際執行的是此段函式,會把參數回傳到外層
}
functionB(callSomeone); // 小明你好 1
// 呼叫 functionB,然後傳入的參數是一個 function,也就是 callSomeone
// 注意傳入的函式並沒有執行
// 傳入 functionB 的是一個完整的函式
```
## arguments 變數
* arguments 是專有名稱,不需另外定義,執行函式時就會自動帶上
* arguments 為類陣列 (物件),可以做基本的陣列操作
* 可使用 for 迴圈取值。
* 沒有大多數陣列可使用的方法,會報錯。
* arguments 可自動帶上傳入所有參數的值
### arguments 類陣列可使用 for 迴圈取值。
```
function callArg(a) {
console.log(a, arguments);
// 1 Arguments(4) [1, 2, 3, "4", callee: ƒ, Symbol(Symbol.iterator): ƒ]
for (let index = 0; index < arguments.length; index++) { // 試著使用 for 迴圈把值取出
console.log(arguments[index]); // 1, 2, 3, '4'
}
}
callArg(1, 2, 3, '4')
```
### arguments 為類陣列不是純陣列,沒有大多數陣列可使用的方法,會報錯。
```
function callArg(a) {
console.log(a, arguments);
arguments.forEach(function() { // 無法使用陣列方法
})
}
callArg(1, 2, 3, '4') // 跳錯,arguments.forEach is not a function
```
## :memo: 學習回顧
:::info
* 函式在運行時會帶入的變數
* para : 傳入的參數。若傳入參數很多,函式內層只會接收第一個參數。
* localVariables : 在函式環境內定義的區域變數。
* arguments : 是一個類陣列。無論傳入多少參數,都可全部接收。
* this : 執行函式時會自動帶入的變數。執行物件內函式的 this 會與一般函式有所不同。
* globalVariable : 全域變數。
* 並非來自於函式本身,是來自於外層的變數。
* 範圍鏈 : 在函式內無法取得此變數,所以函式會向外層尋找,並找到此變數為止。
* 「函式的陳述式」在執行 hositing 時,會把整個代碼移到最前方,但不會比參數更前方。
* 變數 a 在參數一傳入時就已定義好了,hositing 不會影響變數 a 的值。
* 參數名稱可以自己定義
* 參數名稱和傳入的值沒有關聯性
* 只重視參數有幾個值、順序是怎樣…,不會受到外層的名稱所影響
* 若傳入的參數數量不足,會在後方補上 undefined
* 若參數是物件,有傳參考的特性
* 建議不要去調整裡面的屬性參數,會導致原有的物件屬性被調整
* arguments 變數
* arguments 是專有名稱,不需另外定義,執行函式時就會自動帶上
* arguments 為類陣列 (物件),可以做基本的陣列操作
* 可使用 for 迴圈取值。
* 沒有大多數陣列可使用的方法,會報錯。
* arguments 可自動帶上傳入所有參數的值
:::
## :+1: 相關參考文件
:::info
[JavaScript 什麼是Callback函式 (Callback Function)?](https://matthung0807.blogspot.com/2019/05/javascript-callback-callback-function.html)
[你懂 JavaScript 嗎?#23 Callback](https://cythilya.github.io/2018/10/30/callback/)
:::
<style>
.red {
color: red;
}
.green {
color: green;
}
</style>