JavaScript 中的函式是核心概念,隨著使用深入,函式有很多進階技巧和特性可以應用,讓程式碼更具彈性和功能性。
匿名函式(Anonymous Function)沒有名稱,通常用於回呼(callback)或立即執行的情況。箭頭函式(Arrow Function)是匿名函式的簡化寫法,並且有特別的 this
綁定行為。
const greet = function(name) {
return `Hello, ${name}`;
};
console.log(greet("Alice")); // Hello, Alice
const greet = (name) => `Hello, ${name}`;
console.log(greet("Alice")); // Hello, Alice
this
:箭頭函式的 this
綁定於其定義時的上下文,這使得它在物件方法或回呼函式中非常實用。
const person = {
name: "Alice",
greet: function() {
setTimeout(() => {
console.log(`Hello, ${this.name}`); // 'this' 指向 person
}, 1000);
}
};
person.greet(); // Hello, Alice
高階函式是接受另一個函式作為參數,或返回一個函式的函式。這使得它可以用來創建更動態、可重用的程式。
function applyOperation(a, b, operation) {
return operation(a, b);
}
const sum = (x, y) => x + y;
const result = applyOperation(5, 3, sum);
console.log(result); // 8
function multiplier(factor) {
return function(number) {
return number * factor;
};
}
const double = multiplier(2);
console.log(double(5)); // 10
函式柯里化是將多個參數的函式轉換為嵌套的單參數函式,這使得部分應用(partial application)變得更加靈活。
function add(a) {
return function(b) {
return a + b;
};
}
const addFive = add(5);
console.log(addFive(3)); // 8
const add = a => b => a + b;
console.log(add(5)(3)); // 8
立即執行函式是定義後立即執行的函式,常用來創建私有作用域,避免變數污染全局命名空間。
(function() {
const secret = "I am private";
console.log(secret); // I am private
})();
// console.log(secret); // 錯誤:secret 未定義
當函式參數沒有被傳入值時,可以給它一個預設值。這在定義函式時,可以提高函式的靈活性。
function greet(name = "Guest") {
return `Hello, ${name}`;
}
console.log(greet()); // Hello, Guest
console.log(greet("Alice")); // Hello, Alice
rest
參數允許你將不確定數量的參數收集成一個陣列,這在處理可變參數數量時非常有用。而展開運算子可以展開陣列或物件。
function sum(...numbers) {
return numbers.reduce((acc, num) => acc + num, 0);
}
console.log(sum(1, 2, 3, 4)); // 10
const arr1 = [1, 2, 3];
const arr2 = [4, 5];
const combined = [...arr1, ...arr2]; // [1, 2, 3, 4, 5]
const person = { name: "Alice", age: 25 };
const updatedPerson = { ...person, age: 26 }; // { name: "Alice", age: 26 }
記憶化是指將函式的計算結果緩存起來,當再次使用相同參數時,直接返回緩存的結果,這可以用來優化性能,尤其是處理重複計算時。
function memoize(fn) {
const cache = {};
return function(...args) {
const key = JSON.stringify(args);
if (cache[key]) {
return cache[key];
}
const result = fn(...args);
cache[key] = result;
return result;
};
}
const slowFunction = num => {
console.log("Calculating...");
return num * 2;
};
const memoizedFunction = memoize(slowFunction);
console.log(memoizedFunction(5)); // Calculating... 10
console.log(memoizedFunction(5)); // 10 (這次不會計算,直接從緩存中取得結果)
遞迴函式是一種自我呼叫的函式,適合用來解決如樹結構、階乘、斐波那契數列等問題。
function factorial(n) {
if (n === 1) return 1;
return n * factorial(n - 1);
}
console.log(factorial(5)); // 120
函式組合是將多個函式串連起來,將一個函式的輸出作為下一個函式的輸入,這有助於簡化多步驟的邏輯處理。
const compose = (f, g) => x => f(g(x));
const addFive = x => x + 5;
const double = x => x * 2;
const addFiveAndDouble = compose(double, addFive);
console.log(addFiveAndDouble(10)); // (10 + 5) * 2 = 30
this
與 call
、apply
、bind
在 JavaScript 中,this
是動態的,會根據函式的呼叫方式來決定它指向的對象。透過 call
、apply
和 bind
,我們可以手動指定 this
。
call
和 apply
:這兩個方法都用來立即執行函式並明確設定 this
,但 call
是逐一傳遞參數,apply
是用陣列傳遞參數。
function greet(greeting, punctuation) {
console.log(`${greeting}, ${this.name}${punctuation}`);
}
const person = { name: "Alice" };
greet.call(person, "Hello", "!"); // Hello, Alice!
greet.apply(person, ["Hi", "?"]); // Hi, Alice?
bind
:bind
不會立即執行函式,而是返回一個綁定了 this
的新函式。
const person = { name: "Alice" };
const greetPerson = greet.bind(person);
greetPerson("Hello", "!"); // Hello, Alice!
這些進階的 JavaScript 函式技巧能夠大幅提升程式的彈性與可維護性。從高階函式、柯里化到記憶化和遞迴,掌握這些技術可以在寫複雜應用時更加得心應手。