iT邦幫忙

2021 iThome 鐵人賽

0
自我挑戰組

重新開始 JavaScript系列 第 32

[Day31] 參數

Day28 - 函式 中有提到,可以在函式的小括號內放入參數 (parameters),若有多個參數則以 逗號 , 做區格,而參數名稱可以自行定義,與傳入的值無關,如以下範例:

在呼叫函式的小括號內放入值,參數會依序接收

function fun(parameter1, parameter2) {
    console.log(parameter1, parameter2);
}
fun('參數1', '參數2');
// 參數1 參數2

預設參數 (Default parameters)

若傳入的參數的值數量不足,則系統會先給予參數一個 undefined 的值

function fun(parameter1, parameter2, parameter3) {
    console.log(parameter1, parameter2, parameter3);
}
fun('參數1', '參數2');
// 參數1 參數2 undefined

參數預設值

若要避免沒有傳入值,可使用 ES6 的語法,使函式參數有其預設值

function fun(parameter1, parameter2, parameter3 = '我是參數預設值') {
    console.log(parameter1, parameter2, parameter3);
}
fun('參數1', '參數2');
// 參數1 參數2 我是參數預設值

參數與傳參考

若帶入參數的值是物件,他們會指向同一個物件參考路徑,所以就算物件變成參數,依然會維持物件傳參考的特性

function fun(obj) {
    obj.name = 'Mary';
}
var family = {
    name: 'Carol',
};
fun(family);

console.log(family); // {name: 'Mary'}

變數 family 賦予一個物件,並作為參數的值傳入,參數 obj變數 family 會指向同一個物件參考路徑,所以當 參數 obj 改變其物件內容,變數 family 也會受到影響

參數與提升(hoisting)

Day28 - 函式 有提到,函式陳述式在創造階段時,會先在記憶體中將函式陳述式的所有內容做保留

以下在函式陳述式內放入函式陳述式,並將它與參數的名稱命名為一樣,可以發現 參數 nickName函式 nickName 取代,因此在函式內的函式陳述式一樣會被提升,且不會比傳進的 參數 nickName 更前方,因若為更前方,則答案會是 Carol Carol Mary

function fun(nickName) {
    console.log(nickName);
    
    function nickName() {}
    console.log(nickName);
    
    nickName = 'Mary';
    console.log(nickName);
}
fun('Carol');

// ƒ nickName() {}
// ƒ nickName() {}
// Mary

由此可知,上面例子運作流程如下:

// 1. 創造階段
function fun(nickName) {
    console.log(nickName);
    
    function nickName() {}
    console.log(nickName);
    
    nickName = 'Mary';
    console.log(nickName);
}

// 2. 執行階段
fun('Carol');

callback function

參數可以是原始型別,也可以是物件型別,當帶入函式做為參數的值,使此函式成為另一個函式的參數且在另一個函式內調用此函式,稱之為 callback function

function fun(fn) {
    fn('Carol');
}
fun(function(nickName) {
    console.log(nickName);
});

也可以將呼叫 fun 函式 小括號內的函式另外提出來,如下所示:

function fun1(nickName) {
    console.log(nickName);
}
function fun2(fn) {
    fn('Carol');
}
fun2(fun1);

函式引數 (arguments)

上面有提到函式的參數只會提取相對應的數量,而函式引數 (arguments) 則會取得所有傳入的值,並使之成為一個類陣列,而類陣列雖然很像陣列,但無法使用絕大多數的陣列方法

在以下例子中,只用 1 個 參數 a 來接收傳入的值,其餘傳入的值,可利用 arguments 來顯示 (arguments 是專有名稱,不用另外定義)

function fun(a) {
    console.log(a, arguments);
}
fun(1, 2, 3, 4);
// Arguments(4) [1, 2, 3, 4, callee: ƒ, Symbol(Symbol.iterator): ƒ]

其餘參數 (rest parameter)

其餘參數 (rest parameter) 是 ES6 的語法,它可以取得不定數量的參數,作用類似於 函式引數 (arguments),但其餘參數是陣列,arguments 是類陣列

function fun(a, ...others) {
    console.log(a, others);
}
fun(1, 2, 3, 4);
// 1 (3) [2, 3, 4]

需要注意的是其餘參數必須為最後一個參數,且在此參數中只能有一個是其餘參數,否則會出錯

function fun(...others, a) {
    console.log(a, others);
}
fun(1, 2, 3, 4);
// 錯誤訊息 - Uncaught SyntaxError: Rest parameter must be last formal parameter

function fun(a, ...others1, b, ...others2) {
    console.log(a, others1, others2);
}
fun(1, 2, 3, 4, 5, 6);
// 錯誤訊息 - Uncaught SyntaxError: Rest parameter must be last formal parameter

額外補充 - 變數的重複宣告

當宣告一個變數,而此變數已經存在,這個宣告就無任何作用,並不會再變成系統預設值 undefined

var nickName = 'Carol';

var nickName;

console.log(nickName); // Carol

所以,在參數傳遞時,若參數已經定義好值,就算再重複做宣告,不會影響到此參數的值

function fun(nickName) {
    console.log(nickName);
    
    var nickName;
    console.log(nickName);
    
    nickName = 'Mary';
    console.log(nickName);
}
fun('Carol');

// Carol
// Carol
// Mary

參考文獻

六角學院 - JavaScript 核心篇

MDN - 預設參數

MDN - 其餘參數


上一篇
[Day31] 函式
系列文
重新開始 JavaScript32

尚未有邦友留言

立即登入留言