(Day13) 函式基礎與參數介紹

前言

函式在即使非 JavaScript 的程式語言中是非常重要的一塊,我們會根據需求在函式中建立一系列動作,需要的時候便接呼叫對應函式,不管需求是執行 Ajax API ,或是隱藏、顯示畫面中某某區塊,都會將這些需求寫在函式中。

呼叫函式


呼叫函式的方法,使用函式名稱搭配小刮號 ()

1
2
3
4
function Fn1(){
console.log('一般函式')
}
Fn1()


也可以在小刮號中寫入參數,參數會帶到函式中,而函式的參數只跟在函式中建立的變數一樣,他的作用域只存在於函式中。

1
2
3
4
5
function Fn1(num){
console.log(num) //1
}
Fn1(1)
console.log(num) //num


實做中常常看到在函式 return 某個值,而其實 return 的值會直接回傳在呼叫函式的方法中,這種方法常用在會要執行某些重複動作的需求上。

1
2
3
4
5
6
function Fn1(num){
var sum = num + 10
return sum
}

console.log(Fn1(1) , Fn1(2)) //11, 12

arguments


上面有介紹到函式帶參數功能,關於參數也有一個特別的功能,就是 arguments

arguments 這個語法在函式建立時,他也會被一同建立,即使我們不需告變數、參數他也會存在於函式中,而 arguments 其實就是我們呼叫函式時,所有參數組和而成的 類陣列。

1
2
3
4
function Fn1(){
console.log(arguments) //Arguments(3) [1, 2, 3, .... ]
}
Fn1(1,2,3)


什麼是類陣列呢?簡單來講就是一個類似陣列但不是陣列的東西,但是類陣列與陣列最大差異在於可以使用的方法 or 功能會有很大差異,因此我們來看一下範例:

1
2
var a = ['1', '2', '3'];
console.dir(a);


點開變數 a 中的 [[Prototype]] 底下都會是陣列中的方法(太長因此不全部截圖):


arguments 中的 [[Prototype]] 就只有:

可以看的出來類陣列和原始陣列中的方法相差十分多。

參數作用域


當我們參數名稱和函式外層變數相同時,看看花生神魔術

1
2
3
4
5
var name ='Ryder'
function Fn1(name){
console.log(name) // Jack
}
Fn1('Jack')


結果會是以傳入參數為準。
那麼看看對參數使用 = 運算子賦予一個新的值看看結果如何:

1
2
3
4
5
function Fn1(name){
name = 'Annie'
console.log(name) // Annie
}
Fn1('Jack')


結果會發現參數的值確實可以更改,其實參數跟函式中變數的範圍練特性是差不多的,當內層有該參數時,就會優先指向內層參數。

ES6 預設參數


在 ES6 語法中有新增一個預設參數方法,只需在參數旁邊使用 = 運算子賦值,之後呼叫函式時,若沒帶上參數,到了函式中參數便會套上預設的值,但如果呼叫函式時,有帶上參數,便還是以帶上的參數為主,是一個十分方變的功能:

1
2
3
4
5
6
function Fn1(name = 'Annie'){
return name
}
console.log(Fn1()) //Annie
console.log(Fn1('Jack')) //Jack

參數與物件傳參考


先前也有介紹到物件傳參考這個特性,當我們物件傳入參數時,他也會是傳參考, :

1
2
3
4
5
6
var obj1 = { name:'Ryder' }
function Fn1(item){
item.name = 'Annie'
console.log(item.name, obj1.name) // Annie , Annie
}
Fn1(obj1 )

範例中兩個物件的 name 屬性的值也都會改成 'Annie'
不過當我們只是傳入物件中的屬性時,結果並非是傳參考,而僅僅是傳值

1
2
3
4
5
6
var obj1 = { name:'Ryder' }
function Fn1(item){
item = 'Annie'
console.log(item, obj1.name) // Annie , Ryder
}
Fn1(obj1.name)


因此有使用 ES Lint 時,如果有試者修改參數的值,他都會跳出請不要直接修改參數的相關警告,這點就是避免物件傳參考特性發生錯誤。

函式分類


最後來說說函式的分類,在先前 陳述式 /表達式 中有根據建立方法不同,將函式分成:

  • 函示陳述式(具名函式)
  • 函式表達式(匿名函式)

    但這其實是根據這段語法是表達式、陳述式來做區分,或者說函式有沒有名字來做分類的,在 ES6 新增箭頭函式後,一般會把函式分成三種:
  • 一般傳統函式(又可分為 具名函式、匿名函式)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    function Fn1(){
    console.log('傳統具名')
    }
    Fn1()

    var Fn2 = function(){
    console.log('傳統匿名')
    }
    Fn2()
  • 立即函式(IIFE),一般都是以 匿名函式 寫成,雖然也可寫成具名函式,不過這種寫法很少看到:
    1
    2
    3
    (function(){
    console.log('立即函式')
    })()
  • ES6 新增的箭頭函式,箭頭函式一律都是匿名函式,設計上就無法使用具名函式寫成:
    1
    2
    3
    4
    var Fn3 = ()=> {
    console.log('箭頭函式')
    }
    Fn3()

    參考文獻

  • JavaScript 核心篇 (六角學院)