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;
}
}
參考資料
Javascript/function (吳濟聰老師專題知識分享網站)
JavaScript Functions (w3schools) / JavaScript Function Definitions
Javascript Hoisting 提升是什麼? (簡立學長的文章)