引入
在 JavaScript 中,函数里的 this 不一定固定指向某个对象,它和函数的调用方式有关。
call 和 apply 的作用,就是在调用函数时,手动指定函数内部的 this 指向。
正文
定义
定义
call和apply都是函数对象上的方法,用来立即调用函数,并指定函数执行时内部的this。
简单说:
call:指定this,参数一个一个传apply:指定this,参数用数组传
为什么需要它们
有时候一个函数不属于某个对象,但我们希望它在执行时,把 this 当成某个对象来用。
这时就可以使用 call 或 apply。
function sayName() {
console.log(this.name);
}
const user = {
name: "Tom",
};
sayName.call(user); // Tom这里 sayName 本身不是 user 的方法,但通过 call(user),函数内部的 this 就指向了 user。
call 语法
函数.call(thisArg, 参数1, 参数2, ...);thisArg:函数内部this要指向的对象- 后面的参数:传给函数的普通参数
- 会立即执行函数
apply 语法
函数.apply(thisArg, [参数1, 参数2, ...]);- 第一个参数也是指定
this - 第二个参数必须是一个数组或类数组对象
- 也会立即执行函数
例子
使用 call 改变 this
function introduce(age, city) {
console.log(`我叫${this.name},今年${age}岁,来自${city}`);
}
const person = {
name: "小明",
};
introduce.call(person, 18, "北京");执行结果:
我叫小明,今年18岁,来自北京这里 call 做了两件事:
- 把
introduce函数里的this指向person - 把
18和"北京"作为参数传进去
使用 apply 改变 this
function introduce(age, city) {
console.log(`我叫${this.name},今年${age}岁,来自${city}`);
}
const person = {
name: "小红",
};
introduce.apply(person, [20, "上海"]);执行结果:
我叫小红,今年20岁,来自上海apply 和 call 的效果一样,只是传参方式不同。
call 和 apply 的区别
| 方法 | 是否立即执行 | 参数写法 |
|---|---|---|
call | 是 | 参数一个一个写 |
apply | 是 | 参数放在数组里 |
fn.call(obj, a, b);
fn.apply(obj, [a, b]);可以简单记成:
call更适合参数数量明确的情况apply更适合参数已经放在数组里的情况
常见用法
借用对象方法
const person1 = {
name: "Tom",
sayHi() {
console.log(`你好,我是${this.name}`);
},
};
const person2 = {
name: "Jerry",
};
person1.sayHi.call(person2);执行结果:
你好,我是Jerry这里 person2 没有 sayHi 方法,但可以临时借用 person1 的方法。
配合数组参数使用 apply
const nums = [3, 8, 2, 10];
const max = Math.max.apply(null, nums);
console.log(max); // 10Math.max 原本需要一个一个传参数:
Math.max(3, 8, 2, 10);如果参数已经在数组里,就可以用 apply 展开传入。
不过现在更常见的写法是使用展开运算符:
const max = Math.max(...nums);注意事项
call和apply都会立即调用函数- 它们的第一个参数都是用来指定
this call后面的参数是逐个传入apply的第二个参数是数组形式- 如果函数内部没有用到
this,指定this通常没有意义 - 箭头函数没有自己的
this,所以用call或apply不能改变箭头函数的this
箭头函数中的情况
const obj = {
name: "Tom",
};
const fn = () => {
console.log(this.name);
};
fn.call(obj);箭头函数的 this 来自它定义时的外层作用域,不会因为 call 或 apply 改变。
所以如果需要灵活改变 this,一般不要用箭头函数。
理解
可以把 call 和 apply 理解为:临时换一个对象来执行这个函数。
它们不是给对象永久添加方法,而是让函数在这一次执行时,把 this 当成指定的对象。
call 和 apply 的核心区别不在功能,而在传参方式:
- 参数散着写,用
call - 参数已经在数组里,用
apply
引出
理解了 call 和 apply 之后,就可以继续学习 bind,它也能改变 this,但不会立即执行函数。