函式屬於物件的一種,分為「具名函式」和「匿名函式」,包含程式碼片段,可帶入參數,並可被呼叫。
具名函式 Named Function
具名函式顧名思義必須要有函式名稱。
而具名函式能夠在函式內被調用,但是函式中的具名函式無法在函式以外被調用。
function sayHello () {
function inner () {
return console.log('inner')
}
return console.log('Hello!')
}
function callSayHello () {
sayHello() // 具名函式能夠在函式內被調用
}
callSayHello() // Hello!
inner() // inner is not defined 無法被調用
匿名函式 Anonymous Function
函式名稱是可以被忽略的,也就是匿名函式,通常會用表達式來宣告匿名函式,另外立即函式(IIFE)也是屬於匿名函式。
var sayHello = function () {
console.log('Hello!')
;(function () {
console.log('Hey!')
})()
}
sayHello()
// Hello!
// Hey!
陳述式與表達式
- 陳述式:Statement
// 函式陳述式、具名函式
function fn() { ... }
- 表達式:Expression(運算式、表示式)
// 函式表達式、匿名函式
var fn = function() { ... }
函式作用域 Function Scope
函式有屬於自己的作用域,在 ES6 之前,「JavaScript 切分變數有效範圍的最小單位是 function」,所以在這個範圍內的變數只屬於這個函式,一旦離開函式範圍,記憶體就會被釋放掉。
var a = 3
function fn () {
var a = 6
var b = 10
}
fn()
console.log(a) // a = 3
console.log(b) // b is not defined
如果在函式裡面沒有重新宣告變數,那 function 就會向外一層一層找。
function 可以從內層讀取外層宣告的變數,但是外層沒辦法讀取內層宣告的變數,這種行為稱作「範圍鏈(Scope Chain)」。
var msg = 'global'
function outer() {
var msg = 'local'
function inner () {
return msg
}
return inner
}
var innerFunc = outer()
var result = innerFunc()
console.log(result) // local
範例中加了一段 var innerFunc = outer()
,呼叫 outer
回傳的 inner
結果,取得原本從外層無法讀取的 inner
,看似好像把 inner
獨立出來,msg 向外查找所以結果是的外層 global
。
但有個重要觀念:範圍鏈是在函式被定義當下決定的,不是被呼叫的時候。
所以在「定義函式之後,呼叫函式之前」範圍鏈就已經被建立,msg
為 inner
外層的 local
。