前言
大家好 , 我是一名在校大二学生 , 今天学习apply, call, 和 bind , 我决定将三者对比学习 , 分别从 :
- 相同点
- 差异点
- 易错点
横向对比
在 JavaScript 开发中,apply
, call
, 和 bind
是非常常用的函数方法,它们都用于改变函数的 this
上下文。本文将详细介绍这三者的相同点、区别以及易错点,并通过代码示例来加深理解。
相同点
- 改变
this
上下文 :这三个方法都可以改变函数调用时的this
值。 - 立即执行 vs 延迟执行 :
apply
和call
会立即执行函数,而bind
会返回一个新函数,可以在之后调用。
代码示例
js
function greet(name) {
console.log(`Hello, ${name}! I am ${this.name}`);
}
const person = { name: 'Alice' };
// 使用 call
greet.call(person, 'Bob'); // Hello, Bob! I am Alice
// 使用 apply
greet.apply(person, ['Charlie']); // Hello, Charlie! I am Alice
// 使用 bind
const greetAlice = greet.bind(person);
greetAlice('Dave'); // Hello, Dave! I am Alice
差异点
- 参数传递方式:
-
call
:参数以逗号分隔的形式传递。apply
:参数以数组形式传递。bind
:参数以逗号分隔的形式传递,但返回的是一个新函数,可以在之后调用。
代码示例
javascript
function sum(a, b, c) {
return a + b + c;
}
const numbers = [1, 2, 3];
// 使用 call
console.log(sum.call(null, 1, 2, 3)); // 6
// 使用 apply
console.log(sum.apply(null, numbers)); // 6
// 使用 bind
const sum12 = sum.bind(null, 1, 2);
console.log(sum12(3)); // 6
- 返回值:
-
call
和apply
:返回函数的执行结果。bind
:返回一个新函数,可以在之后调用。
代码示例
js
function getGreeting(name) {
return `Hello, ${name}! I am ${this.name}`;
}
const person = { name: 'Alice' };
// 使用 call
const greetingCall = getGreeting.call(person, 'Bob');
console.log(greetingCall); // Hello, Bob! I am Alice
// 使用 apply
const greetingApply = getGreeting.apply(person, ['Charlie']);
console.log(greetingApply); // Hello, Charlie! I am Alice
// 使用 bind
const getGreetingAlice = getGreeting.bind(person);
const greetingBind = getGreetingAlice('Dave');
console.log(greetingBind); // Hello, Dave! I am Alice
易错点
-
this
上下文的默认值:- 在严格模式下,
this
默认为undefined
。 - 在非严格模式下,
this
默认为全局对象(浏览器中是window
,Node.js 中是global
)。
- 在严格模式下,
代码示例
scss
function logThis() {
console.log(this);
}
// 严格模式
(function() {
'use strict';
logThis.call(); // undefined
})();
// 非严格模式
logThis.call(); // window 或 global
bind
返回的新函数的this
上下文:
bind
返回的新函数的this
上下文是固定的,即使使用call
或apply
也无法改变。
代码示例
javascript
function logThis() {
console.log(this);
}
const boundLogThis = logThis.bind({ name: 'Alice' });
boundLogThis.call({ name: 'Bob' }); // { name: 'Alice' }
apply
和call
的性能:
apply
需要将参数数组展开,性能略低于call
。
代码示例
js
function sum(a, b, c) {
return a + b + c;
}
const numbers = [1, 2, 3];
console.time('call');
for (let i = 0; i < 1000000; i++) {
sum.call(null, 1, 2, 3);
}
console.timeEnd('call'); // call: 10ms
console.time('apply');
for (let i = 0; i < 1000000; i++) {
sum.apply(null, numbers);
}
console.timeEnd('apply'); // apply: 15ms
总结
apply
, call
, 和 bind
都是改变函数 this
上下文的强大工具,但它们在参数传递方式、立即执行 vs 延迟执行、返回值等方面有所不同。理解这些差异和易错点,可以帮助我们在实际开发中更灵活地使用这些方法,提高代码的可读性和可维护性。
希望本文对你有所帮助!如果有任何疑问或建议,欢迎在评论区留言交流。