浅谈JS中call()和apply()的区别和用途?

1,667 阅读3分钟

前言:

在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值,如果函数处于非严格模式下,则指定为 nullundefined 时会自动替换为指向全局对象。

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)等。