function

Function

2020/09/22 (補充內容)
2020/10/23 (增加連結)

Basics

function的傳統定義方式 (function declaration)

// function declaration

function times(a, b) {

return a * b;

}


console.log(times(1,2));

//output:

//2

如果把執行結果放到一個變數:

// function declaration

function times(a, b) {

return a * b;

}


var times = times(1,2);

console.log(times);

//output:

//2

注意,這樣的寫法事實上是重新定義times了,所以,times不再是函數了

// function declaration

function times(a, b) {

return a * b;

}

var times = times(1,2);

console.log(times);

//output:

//2

console.log(times(3,4));

//Error: times is not a function

因為在javascript中如果是var,可以重新定義。

但如果用const,function的名稱就不能重複了。這時候,t是個變數,指向這個函數。

// function declaration

function times(a, b) {

return a * b;

}


//const times = times(1,2);

//error: Uncaught SyntaxError: Identifier 'times' has already been declared


const t = times(1,2);

console.log(t);

function expression

變數可以指向一個函數,也就是function expression。

// named function expressions

const times = function times(a,b) {

return a * b;

}

可以省略function的名稱,就成為unnamed function expression

// unnamed function expression

const times = function (a,b) {

return a * b;

}

兩種方法的使用還是有差別的,function的定義是可以寫在後面。

console.log(times(1,2));

function times(a,b) {

return a * b;

}

//output:

//2

但是,用function expression的話,就不能這樣呼叫了!!

console.log(times(1,2));//Error: times not defined

const times = function (a,b) {

return a * b;

}

必須是:

const times = function (a,b) {

return a * b;

}

console.log(times(1,2));

另外,在javascript中,function是可以重複定義的,而且,function寫在哪裡都是可以被呼叫的,下面的程式的結果就可能不是原本的預期,由於times被重複定義,所以,第二個times覆蓋了第一個times,兩個console.log的結果都是24。

function times(a, b) {

return a * b;

}


console.log(times(3,4));

//output:24


function times(a, b) {

return a * b * 2;

}

console.log(times(3,4));

//output:24

建議使用function expression來避免這樣的困擾,因為const是不可以重複的。

Arrow function

如前面的說明,在ES5,可以定義一個unnamed function expression:

const times = function (a,b) {

return a * b;

}

console.log(times(1,2));

arrow function是個在ES6之後的新語法,是較精簡的寫法,對新手而言,是個不容易理解的語法。前面的語法可以寫成:

const times = (a,b) => {

return a*b;

};

console.log(times(1,2));

如果回傳值只有一個expression,可以省略大括號,也可以同時省略return,計算結果就是回傳值。

const times = (a,b) => a*b;

console.log(times(1,2));

如果只傳入一個參數,可省略小括號

const times = a => a*2;

console.log(times(1));

如果沒有參數,就必需要小括號

const times = () => 2*2;

console.log(times());

Callback function

在javascript裡,除了可以傳變數到函數之外,也可以傳一個函數,被傳過去的函數就被稱為callback function。callback function在javascript裡是經常被使用的。我們來看一個例子,在這個例子裡,我們可以把times跟add當成是callback function,傳給calculate,當不同的函數被傳進去時,calculate就會呼叫對應的函數:

function times(a, b) {

return a * b;

}


function add(a, b) {

return a + b;

}


function calculate(a,b,callback){

return callback(a,b);

}


console.log(calculate(1,2,times));

console.log(calculate(1,2,add));


//output:

//2

//3

陣列

陣列裡有些方法會用到callback function,例如,forEach()、map()、filter()、reduce() (JavaScript Array Iteration Methods )

以forEach為例,會去呼叫myFunction,並把陣列裡的每一個內容(value)、內容的位置(index)以及陣列本身(array)傳到myFunction

let numbers = [2, 4, 6, 8, 10];

numbers.forEach(myFunction);


function myFunction(value, index, array) {

console.log(value);

}

//output:

//2

//4

//6

//8

//10

因為我們只用到value,所以,可以改為:

let numbers = [2, 4, 6, 8, 10];

numbers.forEach(myFunction);


function myFunction(value) {

console.log(value);

}

//output:

//2

//4

//6

//8

//10

  • callback function雖然很好用,但是,也會帶來困擾,所以,callback function也有一些替代方案

    • Call back -> Promises & async/await

    • Call back -> Observables

    • Call back -> Generators

參考資料

Generator functions

function *numberToN(N) {

for (let i = 0; i < N; i ++) {

yield i;

}

}

參考資料

內建函數