call 和 apply 的核心區(qū)別在于參數(shù)傳遞方式不同。1. call 的參數(shù)依次列出,適用于參數(shù)固定、明確的場景,如 math.max.call(NULL, 1, 2, 3);2. apply 的參數(shù)為數(shù)組或類數(shù)組,會(huì)自動(dòng)展開,適合參數(shù)為數(shù)組的情況,如 math.max.apply(null, [10, 20, 30]);3. 現(xiàn)代可用 bind 綁定 this 或擴(kuò)展運(yùn)算符替代 apply 的展開功能,但理解 call 和 apply 的本質(zhì)仍很重要。
在 JavaScript 中,call 和 apply 的作用其實(shí)很相似,都是用來改變函數(shù)執(zhí)行時(shí)的 this 指向。它們的核心區(qū)別在于:參數(shù)傳遞的方式不同。
1. 參數(shù)形式不同
這是 call 和 apply 最主要的區(qū)別:
- call 的參數(shù)是依次列出的。
- apply 的參數(shù)是一個(gè)數(shù)組(或類數(shù)組),會(huì)自動(dòng)展開成多個(gè)參數(shù)。
舉個(gè)例子:
function greet(name, age) { console.log(`Hi ${name}, you are ${age} years old. This is ${this.name}`); } const obj = { name: 'World' }; greet.call(obj, 'Alice', 25); // Hi Alice, you are 25 years old. This is World greet.apply(obj, ['Bob', 30]); // Hi Bob, you are 30 years old. This is World
雖然輸出結(jié)果一樣,但調(diào)用方式不一樣:call 是一個(gè)個(gè)傳,apply 是傳數(shù)組。
2. 使用場景上的差異
雖然兩者功能類似,但在實(shí)際開發(fā)中,根據(jù)參數(shù)形式的不同,使用場景也會(huì)略有差別:
? 適合用 call 的情況:
- 參數(shù)數(shù)量固定、明確的時(shí)候。
- 直接傳參更直觀,比如你已經(jīng)知道要傳哪些值。
例如:
Math.max.call(null, 1, 2, 3); // 3
? 適合用 apply 的情況:
- 參數(shù)是數(shù)組或類數(shù)組(如 arguments 對象)。
- 需要?jiǎng)討B(tài)地把一組數(shù)據(jù)作為參數(shù)傳給函數(shù)。
例如:
const nums = [10, 20, 30]; Math.max.apply(null, nums); // 30
這也是為什么以前常看到用 apply 來處理 arguments 對象的原因。
3. 現(xiàn)代替代方案:bind 和擴(kuò)展運(yùn)算符
隨著 es6 的普及,一些原本需要用 call 或 apply 的地方,也可以用更簡潔的方式實(shí)現(xiàn):
- bind 可以綁定 this 并返回新函數(shù)。
- 擴(kuò)展運(yùn)算符 … 可以替代 apply 的數(shù)組展開功能。
例如:
Math.max(...[1, 2, 3]); // 3,比 apply 更清晰
不過這并不影響理解 call 和 apply 的本質(zhì)用途。
總的來說,call 和 apply 的核心差異就是參數(shù)的寫法,其他方面基本一致。
什么時(shí)候用哪個(gè)?記住一句話就行:
如果參數(shù)是數(shù)組,用 apply;如果參數(shù)是分開寫的,用 call。
基本上就這些了。