前言:
在JavaScript中,this指向问题一直是一个老生常谈的问题。很多小伙伴应该都知道在js中,this指向哪里通常是在函数调用的时候才确定的,简单来说就是谁调用了函数则this指向谁,当然,这只是狭义的,更加详细的介绍大家可以去看《你不知道的Javascript》这本书。
call()和apply()这两个方法的作用可以简单归纳为改变this指向,从而让我们的this指向不在是谁调用了函数就指向谁。
1.call()和apply()简介
在JavaScript中,每个函数对象都带有call()和apply()方法,即Function.prototype.call()和Function.prototype.apply(),这两个方法都是挂载在原型上的。
MDN官方解释如下:
call:
call()
方法使用一个指定的this
值和单独给出的一个或多个参数来调用一个函数。
apply:
apply()
方法调用一个具有给定this
值的函数,以及以一个数组(或 类数组对象)的形式提供的参数。
通过官网的解释,大家可能对这两个方法有了一个大致的了解,其实简单来说,call和apply两个方法最主要的作用就是改变this指向。
2. call()和apply()使用方法
call:
function.call( thisArg, arg1, arg2, ...)
apply:
func.apply( thisArg, [argsArray])
参数说明:
thisArg: 函数在运行时的this值,如果函数处于非严格模式下,则指定为 null
或 undefined
时会自动替换为指向全局对象。
arg1, arg2, ...和[argsArray]:函数接收的参数列表。
3.this指向简单示例
代码示例:
<script>
let obj1 = {
name: "张三",
age: 24,
user: function (args) {
console.log("姓名:", this.name);
console.log("年龄:", this.age);
console.log("参数", args);
}
}
let obj2 = {
name: "李四",
age: 30,
user: function () {
console.log("姓名:", this.name);
console.log("年龄:", this.age);
console.log("参数", args);
}
}
// 正常的调用
obj1.user('我是参数');
obj2.user('我是参数');
</script>
输出结果:
输出结果
上段代码中声明了两个对象obj1和obj2,对象中包括了一些常规属性和一个方法属性。然后在最后分别调用了对象中的两个方法,方法中的this指向不出意外的指向了我们的调用者,方法中的name和age就是当前对象中声明的值。
4.使用call()和apply()方法改变this指向
代码示例:
<script>
let obj1 = {
name: "张三",
age: 24,
user: function (args) {
console.log("姓名:", this.name);
console.log("年龄:", this.age);
console.log("参数", args);
}
}
let obj2 = {
name: "李四",
age: 30,
user: function (args) {
console.log("姓名:", this.name);
console.log("年龄:", this.age);
console.log("参数", args);
}
}
// 正常的调用
// obj1.user('我是参数');
// obj2.user('我是参数');
// 改变this指向
obj1.user.call(obj2, "我是参数"); // 使用call方法改变
obj2.user.apply(obj1, ["我是参数"]); // 使用apply方法改变
</script>
输出结果:
输出结果
由上面输出结果可以看出,结果恰好和正常的this指向的结果相反,因为我们使用call方法和apply方法改变了this指向,即当我们调用obj1.user方法时,将this的指向变为了obj2,所以方法中答应出了obj2中的属性值。
5.call与apply的区别
MDN上有这样一段让读者注意的话:
注意:call()方法的作用和 apply() 方法类似,区别就是call()
方法接受的是 参数列表,而apply()
方法接受的是 一个参数数组。
由上面可以得出:两个方法没有什么区别,唯一的区别就是接收的参数不同,一个接收参数列表,一个接收参数数组,才上面的代码示例中也可以看出来。
总结:
call()和apply()两个方法很相似,但是又有些许的不同,在开发中可能很多小伙伴没有用过,但是其实它们的使用场景是很多的,比如:Math.max.apply(null, array)等