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

简介: 前言:在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>

输出结果

1.png


输出结果


上段代码中声明了两个对象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>


输出结果:

2.png



输出结果


由上面输出结果可以看出,结果恰好和正常的this指向的结果相反,因为我们使用call方法和apply方法改变了this指向,即当我们调用obj1.user方法时,将this的指向变为了obj2,所以方法中答应出了obj2中的属性值。


5.call与apply的区别


MDN上有这样一段让读者注意的话:

注意:call()方法的作用和 apply() 方法类似,区别就是call()方法接受的是参数列表,而apply()方法接受的是一个参数数组


由上面可以得出:两个方法没有什么区别,唯一的区别就是接收的参数不同,一个接收参数列表,一个接收参数数组,才上面的代码示例中也可以看出来。


总结:


call()和apply()两个方法很相似,但是又有些许的不同,在开发中可能很多小伙伴没有用过,但是其实它们的使用场景是很多的,比如:Math.max.apply(null, array)等。

相关文章
|
3天前
|
存储 JavaScript 索引
js开发:请解释什么是ES6的Map和Set,以及它们与普通对象和数组的区别。
ES6引入了Map和Set数据结构。Map的键可以是任意类型且有序,与对象的字符串或符号键不同;Set存储唯一值,无重复。两者皆可迭代,支持for...of循环。Map有get、set、has、delete等方法,Set有add、delete、has方法。示例展示了Map和Set的基本操作。
17 3
|
22天前
|
JavaScript 前端开发 索引
问js的forEach和map的区别
JavaScript中的`forEach`和`map`都是数组迭代方法。`forEach`遍历数组但不修改原数组,无返回值;它接受回调函数处理元素。`map`则遍历数组并返回新数组,新数组元素为回调函数处理后的结果。两者都接收元素、索引和数组作为回调函数参数。
20 7
|
25天前
|
JavaScript 前端开发
JS require 与 import 的区别
JS require 与 import 的区别
16 1
|
1月前
|
JavaScript
js开发:请解释什么是ES6的类(class),并说明它与传统构造函数的区别。
ES6的类提供了一种更简洁的面向对象编程方式,对比传统的构造函数,具有更好的可读性和可维护性。类使用`class`定义,`constructor`定义构造方法,`extends`实现继承,并可直接定义静态方法。示例展示了如何创建`Person`类、`Student`子类以及它们的方法调用。
22 2
|
1月前
|
自然语言处理 JavaScript 网络架构
js开发:请解释什么是ES6的箭头函数,以及它与传统函数的区别。
ES6的箭头函数以`=&gt;`定义,简化了函数写法,具有简洁语法和词法作用域的`this`。它无`arguments`对象,不能用作构造函数,不支持`Generator`,且不改变`this`、`super`、`new.target`绑定。适用于简短表达式,常用于异步编程和高阶函数。
18 5
|
2天前
|
JavaScript 前端开发 Oracle
java和JavaScript的区别
java和JavaScript的区别
6 3
|
4天前
|
JavaScript 前端开发
js开发:请解释同步和异步编程的区别。
同步编程按顺序执行,易阻塞;异步编程不阻塞,提高效率。同步适合简单操作,异步适合并发场景。示例展示了JavaScript中同步和异步函数的使用。
14 0
|
8天前
|
算法
Swiper库和Glide.js库的性能有何区别
Swiper和Glide.js是两个流行的响应式轮播图库。Swiper功能强大且灵活,支持多方向滑动,拥有丰富的配置和切换效果,适合复杂需求,其高性能得益于优化的算法和惰性加载。Glide.js则轻量级、快速,专注于基础功能,适合简洁需求。两者各有侧重,选择应基于项目具体需求和性能考虑。
|
12天前
|
存储 JavaScript 前端开发
JavaScript DOM 操作:解释一下 cookie、sessionStorage 和 localStorage 的区别。
Cookie是服务器发送至客户端的文本信息,会随每个请求发送回服务器,适合控制会话状态但可能暴露隐私。SessionStorage仅在当前会话中存储数据,关闭浏览器后清除,适合临时存储如登录状态。LocalStorage则持久保存数据,即使关闭浏览器也不会清除,适用于存储长期设置。三种方式各有侧重,应按需求选择。
15 0
|
15天前
|
JavaScript 前端开发
JQuery和JS的区别有哪些?
JQuery和JS的区别有哪些?
13 0