javascript基础十七:bind、call、apply 区别?如何实现apply、call、bind?

news2024/11/16 18:09:05

在这里插入图片描述
一、作用
call、apply、bind作用是改变函数执行时的上下文,简而言之就是改变函数运行时的this指向
那么什么情况下需要改变this的指向呢?
举个粟子:

var name = '小爱同学'
undefined
const obj = {
    name:'allen ye',
    say:function(){
        console.log(this.name)
    }
}
obj.say()
allen ye // this指向obj对象
undefined
setTimeout(obj.say,0)
小爱同学 // this指向window对象

从上面可以看到,正常情况say方法输出allen ye

但是我们把say放在setTimeout方法中,在定时器中是作为回调函数来执行的,因此回到主栈执行时是在全局执行上下文的环境中执行的,这时候this指向window,所以输出小爱同学

我们实际需要的是this指向obj对象,这时候就需要该改变this指向了

setTimeout(obj.say.bind(obj),0); //allen ye,this指向obj对象

二、区别

下面再来看看apply、call、bind的使用

apply
apply接受两个参数,第一个参数是this的指向,第二个参数是函数接受的参数,以数组的形式传入
改变this指向后原函数会立即执行,且此方法只是临时改变this指向一次

function fn(...args){
    console.log(this,args);
}
let obj = {
    myname:"张三"
}

fn.apply(obj,[1,2]); // this会变成传入的obj,传入的参数必须是一个数组;
fn(1,2) // this指向window

当第一个参数为null、undefined的时候,默认指向window(在浏览器中)

fn.apply(null,[1,2]); // this指向window
fn.apply(undefined,[1,2]); // this指向window

call
call方法的第一个参数也是this的指向,后面传入的是一个参数列表

跟apply一样,改变this指向后原函数会立即执行,且此方法只是临时改变this指向一次

function fn(...args){
    console.log(this,args);
}
let obj = {
    myname:"张三"
}

fn.call(obj,1,2); // this会变成传入的obj,传入的参数必须是一个数组;
fn(1,2) // this指向window

同样的,当第一个参数为null、undefined的时候,默认指向window(在浏览器中)

fn.call(null,[1,2]); // this指向window
fn.call(undefined,[1,2]); // this指向window

bind
bind方法和call很相似,第一参数也是this的指向,后面传入的也是一个参数列表(但是这个参数列表可以分多次传入)
改变this指向后不会立即执行,而是返回一个永久改变this指向的函数

function fn(...args){
    console.log(this,args);
}
let obj = {
    myname:"张三"
}

const bindFn = fn.bind(obj); // this 也会变成传入的obj ,bind不是立即执行需要执行一次
bindFn(1,2) // this指向obj
fn(1,2) // this指向window

小结
从上面可以看到,apply、call、bind三者的区别在于:

  • 三者都可以改变函数的this对象指向
  • 三者第一个参数都是this要指向的对象,如果如果没有这个参数或参数为undefined或null,则默认指向全局window
  • 三者都可以传参,但是apply是数组,而call是参数列表,且apply和call是一次性传入参数,而bind可以分为多次传入
  • bind是返回绑定this之后的函数,apply、call 则是立即执行

三、实现
实现bind的步骤,我们可以分解成为三部分:

  • 修改this指向
  • 动态传递参数
  • 兼容new关键字
// 方式一:只在bind中传递函数参数
fn.bind(obj,1,2)()

// 方式二:在bind中传递函数参数,也在返回函数中传递参数
fn.bind(obj,1)(2)

整体实现代码如下:


Function.prototype.myBind = function(context) {
  if (typeof this !== 'function') {
    throw new TypeError('Error')
  }
  let _this = this
  let args = [...arguments].slice(1)
  return function F() {
    // 判断是否被当做构造函数使用
    if (this instanceof F) {
      return _this.apply(this, args.concat([...arguments]))
    }
    return _this.apply(context, args.concat([...arguments]))
  }
}

call的实现

Function.prototype.myCall = function(context) {
  // 判断是否是undefined和null
  if (typeof context === 'undefined' || context === null) {
    context = window
  }
  context.fn = this
  let args = [...arguments].slice(1)
  let result = context.fn(...args)
  delete context.fn
  return result
}

apply的实现

Function.prototype.myApply = function(context) {
  if (typeof context === 'undefined' || context === null) {
    context = window
  }
  context.fn = this
  let args = arguments[1]
  let result
  if (args) {
    result = context.fn(...args)
  } else {
    result = context.fn()
  }
  delete context.fn
  return result
}

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

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

相关文章

Wi-Fi演进史及关键技术

Wi-Fi演进史及关键技术 文章目录 Wi-Fi演进史及关键技术摘要第一章 Wi-Fi的发展历程1.1 Wi-Fi发展历史1.2 802.11标准的演进 第二章 近代Wi-Fi的核心技术2.1 Wi-Fi 6核心技术2.1.1 OFDMA频分复用技术2.1.2 DL/UL MU-MIMO技术2.1.3 1024QAM2.1.4 空分复用技术(SR&…

Shell脚本攻略:文本三剑客之sed

目录 一、理论 1.sed 二、实验 1.sed命令的寻址打印 2.显示奇偶 3.查找替换 4.后向引用 一、理论 1.sed (1) 概念 sed 英文全称为stream editor流式编辑器,sed 对输入流(文件或来自管道的输入)执行基本文本转换单通过流,…

服务器部署vue

1.下载及安装 打开服务器终端,在终端中输入以下命令,下载nginx安装包。 wget http://nginx.org/download/nginx-1.20.2.tar.gz其中nginx版本可以自己选择,具体版本可查看此链接:nginx news 将下载的压缩包解压,输入指…

chatgpt赋能python:Python列表升序排序:完美的排序方案

Python列表升序排序:完美的排序方案 Python是一种高级编程语言,广泛应用于各种领域,涵盖了从Web开发,数据科学到人工智能。Python强大的语法使其容易编写复杂的程序并处理大型数据集,而Python列表最常用于存储和操作数…

华为OD机试真题 Java 实现【跳房子II】【2023 B卷 100分】,附详细解题思路

一、题目描述 跳房子,也叫跳飞机,是一种世界性的儿童游戏。 游戏参与者需要分多个回合按顺序跳到第1格直到房子的最后一格,然后获得一次选房子的机会,直到所有房子都被选完,房子最多的人获胜。 跳房子的过程中&…

路径规划算法:基于平衡优化器优化的路径规划算法- 附代码

路径规划算法:基于平衡优化器优化的路径规划算法- 附代码 文章目录 路径规划算法:基于平衡优化器优化的路径规划算法- 附代码1.算法原理1.1 环境设定1.2 约束条件1.3 适应度函数 2.算法结果3.MATLAB代码4.参考文献 摘要:本文主要介绍利用智能…

MySQL数据库从入门到精通学习第8天(数据表的查询)

数据表的查询 基本查询语句单表查询聚合函数查询多表连接查询子查询合并查询结果定义表和字段的别名使用正则表达式查询 基本查询语句 SELECT 语句非常的强大,是最常用的查询语句。他具有一个固定的格式,如下: SELECT 查询的内容 FROM 数据…

markdown标注

这里写自定义目录标题 欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants 创建一个自定义列表如何创建一个…

MySQL进阶 -- 存储过程 和 触发器

目录 存储过程介绍存储过程的基本语法变量系统变量用户自定义变量局部变量 if判断 存储过程 介绍 存储过程是事先经过编译并存储在数据库中的一段SQL语句的集合,可以直接调用这些集合(存储过程),调用存储过程可以简化应用开发人…

系列一、MongoDB简介特点应用场景

一、概述 1.1、官方 翻译:MongoDB是一个文档型数据库,旨在方便应用开发和扩展。 1.2、百度百科 1.3、总结 MongoDB 是一个非关系型文档数据库。 二、特点 面向集合存储,易存储对象类型的数据;支持查询以及动态查询&#xff1b…

在 Python 中实现最小堆

树是一种非线性数据结构,其中元素排列在多个级别。 堆是一种基于树的数据结构。 它是一棵完全二叉树,即每个父节点都有两个子节点。 堆实现不同的算法,对其他结构进行排序,对队列进行优先排序等。 堆有两种类型 - 最大和最小。 …

【计算机组成原理·笔记】总线控制

总线控制 总线上连接多个部件,为了解决: 什么时候由哪个部件发送信息如何给信息传送定时如何防止信息丢失如何避免多个部件同时发送如何规定接受信息的部件 等一些列问题,需要总线控制线进行统一管理,这就是总线控制&#xff0…

必须有公网IP吗?内网穿透如何实现外网访问

很多中小型公司或个人都有将自己内网的服务、应用,如远程桌面、网站、数据库、公司的管理系统、FTP、管家婆、监控系统等等,发布到外网,实现异地访问的需求。但往往面临一个普遍的问题,就是没有公网IP,即没有IP v4的公…

KEYSIGHT是德DSOX4034A 示波器 350 MHz

KEYSIGHT是德DSOX4034A 示波器 350 MHz,是德4000 X 系列拥有一系列引以为傲的配置,包括采用了电容触摸屏技术的 12.1 英寸显示屏、InfiniiScan 区域触摸触发、100 万波形/秒捕获率、MegaZoom IV 智能存储器技术和标配分段存储器。 是德DSO-X4034A 主要特…

scrcpy: 在电脑上使用Android手机

文章目录 1. 目的2. 配置2.0 配置思路2.1 安装 scrcpy 2.02.2 添加 udev 规则2.3 手机设置权限2.4 开启 scrcpy 1. 目的 打算在电脑上使用手机上的 App,如京东读书,或QQ。不用电脑版对应软件的原因是,电脑上需要重新登录,有些软件…

JSP SSM 学生综合测评管理系统myeclipse开发mysql数据库springMVC模式java编程计算机网页设计

一、源码特点 JSP SSM 学生综合测评管理系统是一套完善的web设计系统(系统采用SSM框架进行设计开发,springspringMVCmybatis),对理解JSP java编程开发语言有帮助,系统具有完整的源代码和数据库,系统主…

零基础快速搭建私人影音媒体平台

目录 1. 前言 2. Jellyfin服务网站搭建 2.1. Jellyfin下载和安装 2.2. Jellyfin网页测试 3.本地网页发布 3.1 cpolar的安装和注册 3.2 Cpolar云端设置 3.3 Cpolar本地设置 4.公网访问测试 5. 结语 转载自cpolar极点云的文章:零基础搭建私人影音媒体平台【…

RabbitMQ集群架构模式

搭建Mirror镜像集群: 4369是erlang的发现端口 5672是rabbitmq的通信端口 15672是rabbitmq的可视化控制台的端口号 25672是erlang底层发送消息和分配消息的底层端口 firewall-cmd --zonepublic --add-port4369/tcp --permanent firewall-cmd --zonepublic --add-port…

Springboot+vue.js高校校园社交个人博客相册网站系统

基于java语言设计并实现了高校社交系统。该系统基于B/S即所谓浏览器/服务器模式,应用Springboot框架,选择MySQL作为后台数据库。系统主要包括用户、个人动态、个人相册、动态类型、留言板、交流论坛等功能模块。近几年来,由于计算机技术的快速…

chatgpt赋能python:Python列表中如何找出前三名成绩

Python列表中如何找出前三名成绩 在数据分析和编程中,Python语言被广泛使用。其中,列表是Python中最常用的数据类型之一。列表可以存储多个值,并且这些值可以是不同的数据类型。Python列表很强大,因为它提供了许多内置函数和方法…