前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >掌握JavaScript中call()和apply()的精髓,让你的函数调用更加灵活高效

掌握JavaScript中call()和apply()的精髓,让你的函数调用更加灵活高效

作者头像
用户10880571
发布2023-12-22 20:09:52
890
发布2023-12-22 20:09:52
举报
文章被收录于专栏:ssssssssss

前言

JavaScript 是一门非常强大的编程语言,它支持多种编程范式,包括面向对象编程。在 JavaScript 中,我们可以使用 call() 和 apply() 两个方法来调用函数并且改变函数的上下文。这两个方法在 JavaScript 中是非常常用的,但是很多新手对它们的理解还不够深入。在本文中,我们将详细介绍 call() 和 apply() 的区别与用法,帮助读者更好地理解它们。

正文内容

一、call() 和 apply() 的作用

在 JavaScript 中,函数是一等公民,我们可以像使用其他类型的变量一样使用函数。我们可以将函数赋值给变量,将函数作为参数传递给其他函数,或者将函数作为返回值返回给其他函数。但是,函数的上下文是不能像变量一样随意传递的。函数的上下文是指函数内部 this 关键字的指向。在 JavaScript 中,函数的上下文默认是全局对象,但是我们可以通过 call() 和 apply() 方法来改变函数的上下文。

call() 和 apply() 方法的作用都是调用一个函数,并且改变函数的上下文。它们的语法如下:

代码语言:javascript
复制
function.call(thisArg, arg1, arg2, ...)
function.apply(thisArg, [argsArray])

复制

其中,thisArg 表示要改变的函数上下文,arg1、arg2、... 表示函数的参数列表。如果使用 apply() 方法,则参数列表需要以数组的形式传递。这两个方法的区别在于参数的传递方式不同。

二、call() 和 apply() 的区别

call() 和 apply() 的区别在于参数的传递方式不同。call() 方法的参数是一个一个传递的,而 apply() 方法的参数需要以数组的形式传递。下面我们来看一个例子:

代码语言:javascript
复制
function sayHello(name, age) {
  console.log(`Hello, my name is ${name}, I'm ${age} years old.`);
}

sayHello.call(null, 'Tom', 18);
sayHello.apply(null, ['Tom', 18]);

复制

在这个例子中,我们定义了一个函数 sayHello,它接受两个参数 name 和 age。我们使用 call() 和 apply() 方法分别调用这个函数,并且传递相同的参数。在 call() 方法中,我们将参数一个一个传递,而在 apply() 方法中,我们将参数放在一个数组中传递。这两个方法的输出结果是相同的:

代码语言:javascript
复制
Hello, my name is Tom, I'm 18 years old.

复制

除了参数的传递方式不同,call() 和 apply() 还有一些细微的差别。下面我们来详细介绍一下这些差别。

1. 参数传递方式不同

我们已经看到了,call() 和 apply() 方法的参数传递方式不同。这是两个方法最明显的区别。

2. 参数个数不同

在 JavaScript 中,函数的参数个数是可以变化的。我们可以定义一个函数,不传递任何参数,也可以定义一个函数,传递多个参数。在这种情况下,call() 和 apply() 方法的行为也是不同的。

当我们使用 call() 方法调用一个函数时,可以传递任意个数的参数。如果传递的参数个数不足,那么剩余的参数将会被忽略。如果传递的参数个数超过函数定义时的参数个数,那么多余的参数将会被忽略。

当我们使用 apply() 方法调用一个函数时,需要将参数放在一个数组中传递。如果数组中的元素个数不足,那么剩余的参数将会被设置为 undefined。如果数组中的元素个数超过函数定义时的参数个数,那么多余的元素将会被忽略。

下面我们来看一个例子:

代码语言:javascript
复制
function sayHello(name, age) {
  console.log(`Hello, my name is ${name}, I'm ${age} years old.`);
}

sayHello.call(null, 'Tom', 18, 'male');
sayHello.apply(null, ['Tom', 18, 'male']);

复制

在这个例子中,我们定义了一个函数 sayHello,它接受两个参数 name 和 age。我们使用 call() 和 apply() 方法分别调用这个函数,并且传递了三个参数。在 call() 方法中,我们传递了三个参数,但是第三个参数被忽略了。在 apply() 方法中,我们将参数放在一个数组中传递,但是第三个元素被忽略了。这两个方法的输出结果是相同的:

代码语言:javascript
复制
Hello, my name is Tom, I'm 18 years old.

复制

3. thisArg 参数的处理方式不同

在 JavaScript 中,thisArg 参数是用来指定函数的上下文的。在 call() 方法中,thisArg 参数可以为任意值,包括 null 和 undefined。在 apply() 方法中,thisArg 参数必须为对象,如果传递的不是对象,则会自动转换为对象。

下面我们来看一个例子:

代码语言:javascript
复制
function sayHello(name, age) {
  console.log(`Hello, my name is ${name}, I'm ${age} years old. My gender is ${this.gender}.`);
}

var person = {
  gender: 'male'
};

sayHello.call(person, 'Tom', 18);
sayHello.apply(person, ['Tom', 18]);

复制

在这个例子中,我们定义了一个函数 sayHello,它接受两个参数 name 和 age,还使用了 this 关键字来引用 gender 属性。我们定义了一个对象 person,它有一个 gender 属性。我们使用 call() 和 apply() 方法分别调用这个函数,并且将 person 对象作为 thisArg 参数传递。在 call() 方法中,我们将 person 对象直接传递给了 thisArg 参数。在 apply() 方法中,我们将 person 对象放在一个数组中传递。这两个方法的输出结果是相同的:

代码语言:javascript
复制
Hello, my name is Tom, I'm 18 years old. My gender is male.

复制

4. 性能不同

在 JavaScript 中,函数的调用是有一定的开销的。每次调用函数,都需要将函数压入调用栈,然后执行函数体,最后将函数弹出调用栈。在这个过程中,会产生一定的开销。在这种情况下,call() 和 apply() 方法的性能也是不同的。

在大多数情况下,使用 call() 方法调用函数的性能要比使用 apply() 方法调用函数的性能要好。这是因为 call() 方法只需要将参数一个一个传递,而 apply() 方法需要将参数放在一个数组中传递,这会产生一定的开销。但是,这种差别在实际应用中并不是很明显,只有在调用函数的次数非常多的情况下才会产生明显的影响。

三、call() 和 apply() 的用途

call() 和 apply() 方法的用途非常广泛,下面我们来看一些常见的用途。

1. 改变函数的上下文

call() 和 apply() 方法最常见的用途就是改变函数的上下文。在 JavaScript 中,函数的上下文默认是全局对象,但是我们可以使用 call() 和 apply() 方法来将函数的上下文改变为其他对象。这个特性非常有用,可以让我们在不改变函数原有代码的情况下,改变函数的行为。

下面我们来看一个例子:

代码语言:javascript
复制
var person1 = {
  name: 'Tom',
  sayHello: function() {
    console.log(`Hello, my name is ${this.name}.`);
  }
};

var person2 = {
  name: 'Jerry'
};

person1.sayHello(); // 输出:Hello, my name is Tom.
person1.sayHello.call(person2); // 输出:Hello, my name is Jerry.

复制

在这个例子中,我们定义了一个对象 person1,它有一个 sayHello 方法,可以输出自己的名字。我们还定义了一个对象 person2,它也有一个 name 属性。我们使用 call() 方法调用 person1 的 sayHello 方法,并且将 person2 对象作为 thisArg 参数传递。这样,sayHello 方法的上下文就变成了 person2 对象,输出结果也相应地改变了。

2. 借用其他对象的方法

在 JavaScript 中,对象可以通过原型链继承其他对象的方法。但是,有时候我们需要借用其他对象的方法,而不是继承它们。这种情况下,call() 和 apply() 方法就可以派上用场了。

下面我们来看一个例子:

代码语言:javascript
复制
var person = {
  name: 'Tom',
  sayHello: function() {
    console.log(`Hello, my name is ${this.name}.`);
  }
};

var dog = {
  name: 'Snoopy'
};

person.sayHello.call(dog); // 输出:Hello, my name is Snoopy.

复制

在这个例子中,我们定义了一个对象 person,它有一个 sayHello 方法,可以输出自己的名字。我们还定义了一个对象 dog,它也有一个 name 属性。我们使用 call() 方法调用 person 的 sayHello 方法,并且将 dog 对象作为 thisArg 参数传递。这样,sayHello 方法的上下文就变成了 dog 对象,输出结果也相应地改变了。

3. 调用函数并传递参数

除了改变函数的上下文之外,call() 和 apply() 方法还可以调用函数并且传递参数。这种情况下,我们可以使用 call() 方法传递多个参数,也可以使用 apply() 方法将参数放在一个数组中传递

下面我们来看一个例子:

代码语言:javascript
复制
function sum(a, b, c) {
  console.log(`The sum of ${a}, ${b} and ${c} is ${a + b + c}.`);
}

sum.call(null, 1, 2, 3);
sum.apply(null, [1, 2, 3]);

复制

在这个例子中,我们定义了一个函数 sum,它接受三个参数,可以计算它们的和。我们使用 call() 和 apply() 方法分别调用这个函数,并且传递相同的参数。在 call() 方法中,我们将参数一个一个传递,而在 apply() 方法中,我们将参数放在一个数组中传递。这两个方法的输出结果是相同的:

代码语言:javascript
复制
The sum of 1, 2 and 3 is 6.

复制

总结

在 JavaScript 中,call() 和 apply() 方法是非常常用的。它们可以改变函数的上下文,借用其他对象的方法,以及调用函数并且传递参数。这两个方法的区别在于参数的传递方式不同。在大多数情况下,使用 call() 方法调用函数的性能要比使用 apply() 方法调用函数的性能要好。但是,这种差别在实际应用中并不是很明显,只有在调用函数的次数非常多的情况下才会产生明显的影响。

在使用 call() 和 apply() 方法时,需要注意参数的传递方式,以及 thisArg 参数的处理方式。如果不理解这些细节,很容易出现错误。因此,我们需要认真学习这两个方法的用法,掌握它们的细节,才能更好地使用它们。

本文系转载,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文系转载前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 正文内容
    • 一、call() 和 apply() 的作用
      • 二、call() 和 apply() 的区别
        • 1. 参数传递方式不同
        • 2. 参数个数不同
        • 3. thisArg 参数的处理方式不同
        • 4. 性能不同
      • 三、call() 和 apply() 的用途
        • 1. 改变函数的上下文
        • 2. 借用其他对象的方法
        • 3. 调用函数并传递参数
    • 总结
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档