call 和 apply:改变对象行为的秘密武器(上)

在这里插入图片描述

🤍 前端开发工程师(主业)、技术博主(副业)、已过CET6
🍨 阿珊和她的猫_CSDN个人主页
🕠 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》
🍚 蓝桥云课签约作者、已在蓝桥云课上架的前后端实战课程《Vue.js 和 Egg.js 开发企业级健康管理项目》、《带你从入门到实战全面掌握 uni-app》

文章目录

  • 一、引言
    • 介绍 call 和 apply 的概念
    • 为什么需要 call 和 apply
  • 二、 call 和 apply 的语法和参数
    • call 和 apply 的语法和参数
  • 三、 call 和 apply 的区别
    • 调用方式的区别
    • 参数传递的区别
  • 四、使用 call 和 apply 的场景

一、引言

介绍 call 和 apply 的概念

callapply是JavaScript中的两个方法,它们都可以用来调用函数,并改变函数内部的this指向。

  • call的语法为函数名.call(obj,参数1,参数2,参数3……),它将函数作为一个方法绑定到指定对象上进行调用,并且将函数内部的this设置为指定的对象。

  • apply的语法为函数名.apply(obj,[参数1,参数2,参数3……]),它与call类似,但区别在于它将所有参数写在数组里面。

这两个方法的本质都是通过改变对象的内部指针,将特定函数作为一个方法绑定到指定对象上并进行调用。在某些情况下,函数可能需要在特定的对象上调用,而不是在全局上下文中调用,使用callapply方法可以将函数绑定到特定的对象上,以便在调用时能够正确地访问对象的属性和方法。

为什么需要 call 和 apply

在 JavaScript 中,callapply的作用都是在函数调用时改变函数的执行上下文,也就是函数内部的this。它们的使用场景如下:

  • 在函数作为对象方法的情况下,this会指向对象。如果需要在调用函数时改变this的指向,可以使用callapply方法。
  • 在某些情况下,函数可能需要在特定的对象上调用,而不是在全局上下文中调用。使用callapply方法可以将函数绑定到特定的对象上,以便在调用时能够正确地访问对象的属性和方法。

总之,callapply方法可以帮助我们在函数调用时根据需要改变函数的执行环境,从而实现更加灵活和可定制的代码。

二、 call 和 apply 的语法和参数

call 和 apply 的语法和参数

callapply的语法和参数具体如下:

  • call方法:
    • 语法:call((thisObj(,arg1(, arg2(, (,.argN)))))
    • 说明:
      • 第一个参数是表示要绑定的对象,如果调用时不传参,比如call()call(null)call(undefined),那么this都指向window对象。
      • 传递另一个函数的函数名,那么函数中的this指向这个函数的引用。
      • 传递字符串、数值或布尔类型等基础类型,那么函数中的this指向其对应的包装对象,如StringNumberBoolean
      • 传递一个对象,那么函数中的this指向这个对象。
  • apply方法:
    • 语法:apply((thisObj(,argArray)))
    • 说明:
      • 如果argArray不是一个有效的数组或者不是arguments对象,那么将导致一个TypeError
      • 如果没有提供argArraythisObj任何一个参数,那么Global对象将被用作thisObj,并且无法传递任何参数。

callapply的作用都是在函数调用时改变函数的执行上下文,也就是函数内部的this。它们的使用场景如下:

  • 在函数作为对象方法的情况下,this会指向对象。如果需要在调用函数时改变this的指向,可以使用callapply方法。
  • 在某些情况下,函数可能需要在特定的对象上调用,而不是在全局上下文中调用。使用callapply方法可以将函数绑定到特定的对象上,以便在调用时能够正确地访问对象的属性和方法。

三、 call 和 apply 的区别

调用方式的区别

callapply的主要区别在于调用方式不同:

  • call方法的语法为函数名.call(obj,参数1,参数2,参数3……),其中各个参数用逗号分隔。
  • apply方法的语法为函数名.apply(obj,(参数1,参数2,参数3……)),其中所有参数写在数组中。

尽管callapply的作用相同,但它们的使用方式略有不同。在实际应用中,可以根据具体需求选择使用哪种方法来调用函数。

参数传递的区别

callapply在参数传递方面也存在一些区别:

  • call方法可以传递任意数量的参数,参数之间用逗号分隔。
  • apply方法需要将参数传递给一个数组,数组中的元素就是要传递的参数。

下面是一个示例,展示了如何使用callapply方法以及它们之间的区别:

function sum(num1, num2) {return num1 + num2;
}// 使用 call 方法
var result1 = sum.call(null, 10, 20);
console.log(result1); // 使用 apply 方法
var result2 = sum.apply(null, [10, 20]);
console.log(result2); 

在上述示例中,定义了一个sum函数,它接收两个参数并返回它们的和。通过调用sum.call(null, 10, 20),将null作为this值,并传递了两个参数1020sum函数。通过调用sum.apply(null, [10, 20]),同样将null作为this值,并将一个包含参数1020的数组传递给sum函数。

尽管callapply的作用相同,但它们的使用方式略有不同。在实际应用中,可以根据具体需求选择使用哪种方法来调用函数。

四、使用 call 和 apply 的场景

callapply方法主要用于改变对象的上下文,在以下场景中比较常见:

  1. 改变对象的上下文:可以使用callapply方法将函数作为另一个对象的方法进行调用,从而改变函数内部this的值。
var obj1 = {name: 'John',sayHello: function() {console.log('Hello, ' + this.name);}
};var obj2 = {name: 'Alice'
};obj1.sayHello.call(obj2); 

在上面的示例中,有两个对象obj1obj2obj1有一个名为sayHello的方法。通过使用call方法,将obj2作为this值传递给sayHello方法,输出结果将会是Hello, Alice

  1. 实现继承:可以使用callapply方法来模拟继承。
function Parent() {this.name = 'parent';
}Parent.prototype.sayGoodbye = function() {console.log('Goodbye, ' + this.name);
}function Child() {// 调用父类构造函数,实现属性继承Parent.call(this); this.type = 'child';
}// 子类的原型指向父类的实例,实现方法继承
Child.prototype = Object.create(Parent.prototype); 
// 修复构造函数指向问题,确保子类的构造函数指向自己
Child.prototype.constructor = Child; var child = new Child();
child.sayGoodbye(); 

在上面的示例中,创建了一个父类Parent和一个子类Child。通过使用call方法,在子类的构造函数中调用父类的构造函数,实现属性继承。然后,通过设置子类的原型指向父类的实例,实现方法继承。最后,创建子类的实例,并调用sayGoodbye方法。

除了上述常见场景外,callapply方法还可以用于其他一些情况,例如在某些框架中进行事件绑定、延迟执行等。具体使用场景取决于具体的需求和代码结构。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/226675.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

类加载的过程

类加载是Java虚拟机(JVM)在运行时加载字节码的过程。这个过程包括类的加载(Loading)、验证(Verification)、准备(Preparation)、解析(Resolution)和初始化(Initializatio…

IntelliJ IDEA 运行 若依分离版后端

一、本地运行 一、选择打开IntelliJ IDEA项目 二、选择若依项目 如:java123 三、等待右下角的准备工作(有进度条的)完成 四、修改MySQL 五、修改资源上传目录 六、修改redis 七、然后点击运行 八、成功图 九、测试访问 二、部署服务器运行 …

第4章-第2节-Java中的数组相关知识点

1、一维数组 1)、数组使用过程中可能出现的问题 常见的运行时异常: 1).java.lang.ArrayIndexOutOfBoundsException: 数组下标越界异常 2).java.lang.NullPointerException: 空指针异常 2)、参数传递 两种…

初级数据结构(五)——树和二叉树的概念

文中代码源文件已上传&#xff1a;数据结构源码 <-上一篇 初级数据结构&#xff08;四&#xff09;——队列 | NULL 下一篇-> 1、树结构&#xff08;Tree&#xff09; 1.1、树结构的特点 自然界中的树由根部开始向上生长&#xff0c;随机长出分支&…

开源数据集下载地址

cvmart https://www.cvmart.net/dataSets 目标检测&#xff1a;https://www.cvmart.net/dataSets/detail/707人脸识别&#xff1a;https://www.cvmart.net/dataSets/detail/888CIFAR&#xff1a;https://www.cvmart.net/dataSets/detail/774 voc yolo代码中data目录&#x…

汇编语言学习(1)

更好的阅读体验&#xff0c;请点击 汇编语言学习 | YinKais Blog 简介 我为什么要学汇编 因为想在寒假手写一下操作系统玩玩&#xff0c;所以提前学一学汇编&#xff0c;到时候放假就可以直接上手写了。 什么是汇编语言 由于处理器只能理解机器语言指令&#xff0c;即 0 和…

第十七章 : Spring Boot 集成RabbitMQ(一)

第十七章 : Spring Boot 集成RabbitMQ(一) 前言 本章介绍RabbitMQ的核心概念和消息中间件中非常重要的协议——AMQP协议,然后介绍Direct、Topic、Headers、Fanout等交换机的作用和特点;RabbitMQ的五种消息发送模式-简单队列、工作队列、发布订阅、路由、广播;以及Rabbi…

对自己的博客网站进行DOS攻击

对自己的博客网站进行DOS攻击 先说明一点,别对别人的网站进行ddos/dos攻击(dos攻击一般短时间攻击不下来),这是违法的,很多都有自动报警机制,本篇博客仅用于学习,请勿用于非法用途 安装kaili Linux 进入KALI官网,下载iso镜像文件 vmware新建虚拟机,选择自定义 点击下一步 …

C#基础——面向对象(封装 继承 多态)

C# 属于面向对象编程&#xff0c;所谓"万物皆对象"。 面向对象编程的三大特性&#xff1a;封装、继承、多态。 1、封装&#xff1a;封装是一种将数据和方法包含在类中的机制&#xff0c;以避免外部代码直接访问和修改类的内部数据。可以使用访问修饰符&#xff08;…

ROS-ROS运行管理-工作空间覆盖;节点、话题、参数名称重名

文章目录 一、工作空间覆盖二、节点名称重名2.1 rosrun设置命名空间与重映射2.2 launch文件设置命名空间与重映射2.3 编码设置命名空间与重映射 三、话题名称设置3.1 rosrun设置话题重映射3.2 launch文件设置话题重映射3.3 编码设置话题名称 四、参数名称设置4.1 rosrun设置参数…

Redis部署文档

Redis部署文档 简介 这份文档旨在指导如何在Docker环境中部署Redis。 步骤 1. 安装Docker和Docker Compose 确保在部署之前已经安装了Docker和Docker Compose。 2. 创建Docker Compose文件 在项目根目录创建一个docker-compose.yaml文件&#xff0c;并将以下内容复制到文…

[笔记] wsl2 下使用 qemu/grub 模拟系统启动(多分区)

首先创建一块虚拟硬盘: dd bs512 count204800 if/dev/zero ofhd.img然后使用 losetup -f 将其关联为本地回环设备 losetup -f hd.img # 关联 hd.img 到空闲回环设备上 losetup -a /dev/loop0: [2080]:409 (/root/code/demo05/hd.img) # 查看刚刚关联到了哪里,这里关联到了 /d…

Github与Gitlab

学习目标 能够使用GitHub创建远程仓库并使用能够安装部署GitLab服务器能够使用GitLab创建仓库并使用掌握CI/CD的概念掌握蓝绿部署, 滚动更新,灰度发布的概念 GitHub是目前最火的开源项目代码托管平台。它是基于web的Git仓库&#xff0c;提供公有仓库和私有仓库&#xff0c;但私…

使用Go实现一个百行聊天服务器

前段时间, redis作者不是整了个c语言版本的聊天服务器嘛, 地址, 代码量拢共不过百行. 于是, 心血来潮下, 我也整了个Go语言版本. 简单来说就是实现了一个聊天室的功能. 将所有注释空行都去掉, 刚好100行实现. 废话不多说, 先上代码: package mainimport ("fmt"&quo…

SoC中跨时钟域的信号同步设计(单比特同步设计)

一、 亚稳态 在数字电路中&#xff0c;触发器是一种很常用的器件。对于任意一个触发器&#xff0c;都由其参数库文件规定了能正常使用的“建立时间”&#xff08;Setup time&#xff09;和“保持时间”&#xff08;Hold time &#xff09;两个参数。“建立时间”是指在时钟…

【MySQL学习之基础篇】多表查询

文章目录 1. 多表关系1.1. 一对多1.2. 多对多1.3. 一对一 2. 多表查询概述2.1. 数据准备2.2. 概述 3. 查询的分类3.1. 内连接查询3.2. 外连接查询3.3. 自连接3.3.1. 自连接查询3.3.2. 联合查询 3.4. 子查询3.4.1. 概述3.4.2. 标量子查询3.4.3. 列子查询3.4.4. 行子查询3.4.5. 表…

python+requests+pytest 接口自动化实现

最近工作之余拿公司的项目写了一个接口测试框架&#xff0c;功能还不是很完善&#xff0c;算是抛砖引玉了&#xff0c;欢迎各位来吐槽。 主要思路&#xff1a; ①对 requests 进行二次封装&#xff0c;做到定制化效果 ②使用 excel 存放接口请求数据&#xff0c;作为数据驱动 ③…

LeetCode(60)K 个一组翻转链表【链表】【困难】

目录 1.题目2.答案3.提交结果截图 链接&#xff1a; K 个一组翻转链表 1.题目 给你链表的头节点 head &#xff0c;每 k 个节点一组进行翻转&#xff0c;请你返回修改后的链表。 k 是一个正整数&#xff0c;它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍&#xf…

Modbus转Profinet网关使用方法

Modbus转Profinet网关&#xff08;XD-MDPN100/200&#xff09;是用于将Modbus协议和Profinet协议进行转换并进行通迅的设备。Modbus转Profinet网关&#xff08;XD-MDPN100/200&#xff09;无论是新项目还是改造项目都可轻松配置完成通迅互联。 正确的安装和配置对于确保设备的正…

低代码核心能力详解:简化应用开发的新思路

低代码平台作为一种快速地应用开发解决方法&#xff0c;为中小企业实现数字化转型提供了机会。但是&#xff0c;对于一些刚开始触碰低代码平台的企业来说&#xff0c;了解其核心能力是很重要的。本文将详细分析低代码平台的核心能力&#xff0c;并在挑选低代码平台以前为中小企…