当前位置: 首页 > news >正文

JavaScript中的this指向,call、apply、bind的简单实现

JavaScript中的this

this是JavaScript中一个特殊关键字,用于指代当前执行上下文中的对象。它的难以理解之处就是值不是固定的,是再函数被调用时根据调用场景动态确定的,主要根据函数的调用方式来决定this指向的对象。this 的值在函数被调用时动态确定,以下是几种常见的情况:

  1. 全局上下文中:
    当在全局作用域中调用函数时,this 指向全局对象。在浏览器环境中,这个全局对象是 window 对象。

    console.log(this); // 在浏览器中,输出为 Window 对象
    
  2. 函数作为对象的方法:
    当函数作为对象的方法被调用时,this 指向调用该方法的对象。

    const obj = {property: 'value',printProperty: function() {console.log(this.property);}
    };obj.printProperty(); // 输出 'value'
    
  3. 构造函数中:
    在使用 new 关键字创建实例时,构造函数内部的 this 指向即将创建的新实例。

    function Person(name) {this.name = name;
    }const person = new Person('Alice');
    console.log(person.name); // 输出 'Alice'
    
  4. 显式绑定:
    使用call、apply、bind方法可以显式指定this的绑定对象。

function greet(message) {console.log(`${message}, ${this.name}!`);
}const person = { name: 'Bob' };greet.call(person, 'Hello'); // 输出 'Hello, Bob!'
  1. 箭头函数:
    箭头函数不绑定this,它会捕获外层作用域的this值作为自己的this。
const obj = {method: function() {const arrowFunc = () => {console.log(this === obj);};arrowFunc();}
};obj.method(); // 输出 true
  1. class中的this:
    类中的this默认指向类的实例对象。
class Rectangle {constructor(width, height) {this.width = width;this.height = height;}
}const rect = new Rectangle(10, 20);
console.log(rect.width); // 输出 10
  1. 事件绑定
    事件绑定中的this是指向触发事件的dom元素。
const button = document.getElementById('myButton');button.addEventListener('click', function() {console.log(this === button);
});
// 在按钮点击时输出 true

如何改变this指向

改变 this 指向是在 JavaScript 中常见的需求,特别是当你想要在不同的上下文中调用函数时。以下是几种常见的方法来改变 this 指向:

  1. 使用 call 方法:
    call 方法允许你显式地指定函数内部的 this 值,并且传递参数列表。第一个参数是要绑定的 this 值,后面的参数是函数的参数。

    function greet(message) {console.log(`${message}, ${this.name}!`);
    }const person = { name: 'Alice' };greet.call(person, 'Hello'); // 输出 'Hello, Alice!' 这里把this绑定给person对象
    
  2. 使用 apply 方法:
    apply 方法与 call 类似,但它接受一个数组或类数组对象作为参数,其中的元素将作为函数参数传递。

    function greet(message) {console.log(`${message}, ${this.name}!`);
    }const person = { name: 'Bob' };greet.apply(person, ['Hi']); // 输出 'Hi, Bob!'
    
  3. 使用 bind 方法:
    bind 方法创建一个新函数,将 this 值永久地绑定,并可以预先设置部分参数。原函数不会受到影响。

    function greet(message) {console.log(`${message}, ${this.name}!`);
    }const person = { name: 'Charlie' };
    const greetPerson = greet.bind(person);greetPerson('Hey'); // 输出 'Hey, Charlie!'
    
  4. 使用箭头函数:
    箭头函数不会绑定独立的 this 值,而是捕获其外部函数的 this 值。

    const obj = {method: function() {const arrowFunc = () => {console.log(this === obj);};arrowFunc();}
    };obj.method(); // 输出 true
    

call和apply区别

  1. bind 方法:

    • bind 方法创建一个新函数,将原函数的 this 值永久绑定到指定的对象,并可以在调用时传递参数。
    • 它不会立即执行原函数,而是返回一个新的函数,需要手动调用新函数以执行原函数。
    • bind 方法不会改变原函数的上下文,而是返回一个新函数。
  2. call 方法:

    • call 方法立即调用函数,并指定函数内部的 this 值,同时可以传递参数列表。
    • 它的第一个参数是要绑定的 this 值,后续的参数会作为函数的参数传递。
  3. apply 方法:

    • apply 方法也立即调用函数,并指定函数内部的 this 值,但参数传递方式不同。
    • 它的第一个参数是要绑定的 this 值,第二个参数是一个数组(或类数组对象),其中的元素会作为函数的参数传递。

实现call、apply、bind

这里实现简化版的,核心思路是:

  1. 将函数设为传入对象的一个属性
  2. 执行该函数
  3. 删除该函数(临时函数调用完成删除,防止内存泄漏,以免context 对象造成污染)
  4. 返回结果或传入的this

call

js
Function.prototype.myCall = function(context, ...args) {context = context || window;const fn = Symbol();context[fn] = this;const result = context[fn](...args);delete context[fn];return result;
}

apply

js
Function.prototype.myApply = function(context, args) {context = context || window;const fn = Symbol();context[fn] = this;let result;if(args) {result = context[fn](...args);} else {result = context[fn]();}delete context[fn];return result;
}

bind

js
Function.prototype.myBind = function(context, ...outerArgs) {context = context || window;const _this = this;return function(...innerArgs) {context[fn] = _this;const result = context[fn](...outerArgs, ...innerArgs);delete context[fn];return result;}
}

相关文章:

JavaScript中的this指向,call、apply、bind的简单实现

JavaScript中的this this是JavaScript中一个特殊关键字,用于指代当前执行上下文中的对象。它的难以理解之处就是值不是固定的,是再函数被调用时根据调用场景动态确定的,主要根据函数的调用方式来决定this指向的对象。this 的值在函数被调用时…...

Linux学习之基本指令一

在学习Linux下的基本指令之前首先大家要知道Linux下一切皆目录,我们的操作基本上也都是对目录的操作,这里我们可以联想我们是如何在windows上是如何操作的,只是形式上不同,类比学习更容易理解。 目录 01.ls指令 02. pwd命令 0…...

appium默认60秒关闭应用的问题

问题:appium默认启动一个应用的session过期时间是60秒到时间会自动停了刚启动的应用,工作台打印:info: [debug] We shut down because no new commands came in的日志 分析:--command-timeout 60 The default command timeout fo…...

Docker 容器内无法使用vim命令 解决方法

目录 1. 问题所示2. 原理分析3. 解决方法1. 问题所示 进入Docker容器后 无法使用vim编辑器,出现如下问题:bash: vim: command not found 如图所示: 想着通过apt-get 安装vim,出现如下问题: root@b9f0fd330d5b:/# apt-get install vim Reading package lists... Done B…...

Django的简介安装与配置及两大设计模式

一.Djang的介绍 1.Django是什么 Django 是使用 Python 语言开发的一款免费而且开源的 Web 应用框架。 由于 Python 语言的跨平台性,所以 Django 同样支持 Windows、Linux 和 Mac 系统。 在 Python 语言炽手可热的当下,Django 也迅速的崛起,在…...

Mybatis分页插件——PageHelper

一、定义 PageHelper用在mybatis插件里面,可以自动的为最近的sql语句进行分页查询,提供分页的页码size和每页数量num,在查询过程中hi自动的拼接limit关键字,不用再改写sql语句了 在PageHelper.startPage(); 在启动查询…...

k8s认证详解 k8s证书详解 2023推荐

推荐阅读 https://www.yii666.com/blog/478731.html?actiononAll 在 Kube-apiserver 中提供了很多认证方式,其中最常用的就是 TLS 认证,当然也有 BootstrapToken,BasicAuth 认证等,只要有一个认证通过,那么 Kube-api…...

php初解

php是什么? PHP,全称 Hypertext Preprocessor ,中文翻译“超文本预处理器”。 PHP是一种被广泛应用的开源通用脚本语言,尤其适用于 Web 开发。 拥有快速,灵活,实用的特点,PHP能做任何事&#xf…...

【C语言】回调函数,qsort排序函数的使用和自己实现,超详解

文章目录 前言一、回调函数是什么二、回调函数的使用1.使用标准库中的qsort函数2.利用qsort函数对结构体数组进行排序 三、实现qsort函数总结 先记录一下访问量突破2000啦,谢谢大家支持!!! 这里是上期指针进阶链接,方便…...

PHP手术麻醉系统源码,自动生成麻醉和护理医疗文书

一套手术麻醉系统源码,可二次开发 手术室麻醉临床信息系统(AIMS)是应用于医院手术室、麻醉科室的计算机软件系统。该系统针对整个围术期,对病人进行全程跟踪与信息管理,自动集成病人HIS、LIS、RIS、PACS信息&#xff0…...

内网穿透实战应用——【通过cpolar分享本地电脑上有趣的照片:发布piwigo网页】

通过cpolar分享本地电脑上有趣的照片:发布piwigo网页 文章目录 通过cpolar分享本地电脑上有趣的照片:发布piwigo网页前言1. 设定一条内网穿透数据隧道2. 与piwigo网站绑定3. 在创建隧道界面填写关键信息4. 隧道创建完成 总结 前言 首先在本地电脑上部署…...

iPhone删除的照片能恢复吗?不小心误删了照片怎么找回?

iPhone最近删除清空了照片还能恢复吗?大家都知道,照片对于我们来说是承载着美好回忆的一种形式。它记录着我们的平淡生活,也留住了我们的美好瞬间,具有极其重要的纪念价值。 照片不小心误删是一件非常难受的事,那么iP…...

LeetCode--HOT100题(32)

目录 题目描述:138. 复制带随机指针的链表(中等)题目接口解题思路代码 PS: 题目描述:138. 复制带随机指针的链表(中等) 给你一个长度为 n 的链表,每个节点包含一个额外增加的随机指针 random &…...

SAP MM学习笔记24-以评估收货(评价)和非评估收货(非评价)

SAP 中 有评价入库(评估收货)和非评价入库(非评估收货)两种入库方式。 一般来说在库品目会采用评价入库,而消费品目,会采用非评价入库。 其实评价入库,非评价入库对外都无所谓的,人…...

Hadoop的DataNode无法启动的解决方案

Hadoop重启一次,里面的数据需要重新导入,发现无法导入数据,查看jps发现是DataNode没有启动,重新启动发现也无法启动,原因是前面重新启动NameNode,里面的文件格式化一次,DataNode的文件不一致&am…...

re中的match和search有什么区别?

问题:请说明以下re模块中的match和search有什么区别? re.match()与re.search()的区别 re.match()只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,结果返回None,而re.search()匹配整个字符串,直到找到一个匹配 re.search() re.search()扫描整个字符串并…...

《内网穿透》无需公网IP,公网SSH远程访问家中的树莓派

文章目录 前言 如何通过 SSH 连接到树莓派步骤1. 在 Raspberry Pi 上启用 SSH步骤2. 查找树莓派的 IP 地址步骤3. SSH 到你的树莓派步骤 4. 在任何地点访问家中的树莓派4.1 安装 Cpolar内网穿透4.2 cpolar进行token认证4.3 配置cpolar服务开机自启动4.4 查看映射到公网的隧道地…...

.net连接mysql,提示找不到请求的 .Net Framework Data Provider。可能没有安装

开发完成的.net程序需要连接mysql数据库,在个人电脑上运行没问题,别人运行时提示“提示找不到请求的 .Net Framework Data Provider。可能没有安装”。经过查询,安装Connector/NET 8.1.0,下载地址如下所示: https://d…...

销售自动化管理软件是什么,销售自动化管理软件有什么优势

阅读本文您可以了解:1、销售自动化管理软件是什么;2、销售自动化管理软件的优势 一、销售自动化管理软件是什么 销售自动化管理软件是一种用于帮助企业有效管理销售流程和客户关系的工具。它集成了各种功能和工具,以简化和自动化销售团队的任…...

MySQL 函数

mysql 函数语法 create function 函数名(参数名 参数类型,。。。) returns type —返回值类型 ----returns 有个 s [characteristics…] begin 函数体 ### 函数体中肯定有 return 语句 end 参数列表 指定参数为 IN | out | INOUT 只对存储过程…...

模型参数、模型存储精度、参数与显存

模型参数量衡量单位 M:百万(Million) B:十亿(Billion) 1 B 1000 M 1B 1000M 1B1000M 参数存储精度 模型参数是固定的,但是一个参数所表示多少字节不一定,需要看这个参数以什么…...

安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件

在选煤厂、化工厂、钢铁厂等过程生产型企业,其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进,需提前预防假检、错检、漏检,推动智慧生产运维系统数据的流动和现场赋能应用。同时,…...

1.3 VSCode安装与环境配置

进入网址Visual Studio Code - Code Editing. Redefined下载.deb文件,然后打开终端,进入下载文件夹,键入命令 sudo dpkg -i code_1.100.3-1748872405_amd64.deb 在终端键入命令code即启动vscode 需要安装插件列表 1.Chinese简化 2.ros …...

linux 错误码总结

1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...

【C++从零实现Json-Rpc框架】第六弹 —— 服务端模块划分

一、项目背景回顾 前五弹完成了Json-Rpc协议解析、请求处理、客户端调用等基础模块搭建。 本弹重点聚焦于服务端的模块划分与架构设计,提升代码结构的可维护性与扩展性。 二、服务端模块设计目标 高内聚低耦合:各模块职责清晰,便于独立开发…...

全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比

目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...

return this;返回的是谁

一个审批系统的示例来演示责任链模式的实现。假设公司需要处理不同金额的采购申请,不同级别的经理有不同的审批权限: // 抽象处理者:审批者 abstract class Approver {protected Approver successor; // 下一个处理者// 设置下一个处理者pub…...

安宝特案例丨Vuzix AR智能眼镜集成专业软件,助力卢森堡医院药房转型,赢得辉瑞创新奖

在Vuzix M400 AR智能眼镜的助力下,卢森堡罗伯特舒曼医院(the Robert Schuman Hospitals, HRS)凭借在无菌制剂生产流程中引入增强现实技术(AR)创新项目,荣获了2024年6月7日由卢森堡医院药剂师协会&#xff0…...

【Linux手册】探秘系统世界:从用户交互到硬件底层的全链路工作之旅

目录 前言 操作系统与驱动程序 是什么,为什么 怎么做 system call 用户操作接口 总结 前言 日常生活中,我们在使用电子设备时,我们所输入执行的每一条指令最终大多都会作用到硬件上,比如下载一款软件最终会下载到硬盘上&am…...

智能职业发展系统:AI驱动的职业规划平台技术解析

智能职业发展系统:AI驱动的职业规划平台技术解析 引言:数字时代的职业革命 在当今瞬息万变的就业市场中,传统的职业规划方法已无法满足个人和企业的需求。据统计,全球每年有超过2亿人面临职业转型困境,而企业也因此遭…...