在 JavaScript 中,函數是物件,因此它們有內建方法可以用來控制執行方式。
這些方法包括 .call()
、.apply()
和 .bind()
,主要用來改變函數執行時的 this 指向或傳遞參數,特別在物件導向或繼承中很有用。
立即執行函數,並指定 this 的值,參數逐個傳入。
function greet(greeting) {
console.log(`${greeting}, I'm ${this.name}`);
}
const person = { name: "Alice" };
greet.call(person, "Hello"); // "Hello, I'm Alice"
解析:
實際應用:借用其他物件的方法
const person1 = {
name: "Alice",
greet: function() {
console.log(`Hi, ${this.name}`);
}
};
const person2 = { name: "Bob" };
person1.greet.call(person2); // "Hi, Bob"
與 .call() 類似,立即執行函數並指定 this,但參數以陣列形式傳入。
function introduce(greeting, time) {
console.log(`${greeting}, I'm ${this.name}, it's ${time}`);
}
const person = { name: "Bob" };
introduce.apply(person, ["Hey", "morning"]); // "Hey, I'm Bob, it's morning"
解析:
與 .call() 的差異:
實際應用:處理動態參數
const numbers = [1, 2, 3, 4];
console.log(Math.max.apply(null, numbers)); // 4
不立即執行,而是返回一個新函數,永久綁定指定的 this 和部分參數。
function sayHello(greeting) {
console.log(`${greeting}, I'm ${this.name}`);
}
const person = { name: "Charlie" };
const boundFn = sayHello.bind(person, "Hola");
boundFn(); // "Hola, I'm Charlie"
解析:
與 .call() / .apply() 的差異:
實際應用:事件處理
const obj = {
name: "Dog",
bark: function() {
console.log(`${this.name} says woof`);
}
};
const boundBark = obj.bark.bind(obj);
setTimeout(boundBark, 1000); // 1秒後 "Dog says woof"
在非嚴格模式下,this 指向全域物件(window 或 global)。
在嚴格模式下,this 保持 null 或 undefined。
"use strict";
function checkThis() {
console.log(this);
}
checkThis.call(null); // null
後續無法用 .call() 或 .apply() 改變 this
const bound = sayHello.bind({ name: "Fixed" });
bound.call({ name: "New" }); // "Hola, I'm Fixed"(不會變成 New)
.bind() 創建新函數,若大量使用可能增加記憶體負擔。
.call():立即執行,指定 this,逐個傳參。
.apply():立即執行,指定 this,陣列傳參。
.bind():返回新函數,綁定 this 和部分參數。
用途:控制 this,實現方法借用或繼承。