当前位置: 首页 > 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 只对存储过程…...

微软PowerBI考试 PL300-选择 Power BI 模型框架【附练习数据】

微软PowerBI考试 PL300-选择 Power BI 模型框架 20 多年来,Microsoft 持续对企业商业智能 (BI) 进行大量投资。 Azure Analysis Services (AAS) 和 SQL Server Analysis Services (SSAS) 基于无数企业使用的成熟的 BI 数据建模技术。 同样的技术也是 Power BI 数据…...

在rocky linux 9.5上在线安装 docker

前面是指南,后面是日志 sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo dnf install docker-ce docker-ce-cli containerd.io -y docker version sudo systemctl start docker sudo systemctl status docker …...

渗透实战PortSwigger靶场-XSS Lab 14:大多数标签和属性被阻止

<script>标签被拦截 我们需要把全部可用的 tag 和 event 进行暴力破解 XSS cheat sheet&#xff1a; https://portswigger.net/web-security/cross-site-scripting/cheat-sheet 通过爆破发现body可以用 再把全部 events 放进去爆破 这些 event 全部可用 <body onres…...

YSYX学习记录(八)

C语言&#xff0c;练习0&#xff1a; 先创建一个文件夹&#xff0c;我用的是物理机&#xff1a; 安装build-essential 练习1&#xff1a; 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件&#xff0c;随机修改或删除一部分&#xff0c;之后…...

【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 初始化服务器)

服务端执行命令请求的过程 【专栏简介】【技术大纲】【专栏目标】【目标人群】1. Redis爱好者与社区成员2. 后端开发和系统架构师3. 计算机专业的本科生及研究生 初始化服务器1. 初始化服务器状态结构初始化RedisServer变量 2. 加载相关系统配置和用户配置参数定制化配置参数案…...

MODBUS TCP转CANopen 技术赋能高效协同作业

在现代工业自动化领域&#xff0c;MODBUS TCP和CANopen两种通讯协议因其稳定性和高效性被广泛应用于各种设备和系统中。而随着科技的不断进步&#xff0c;这两种通讯协议也正在被逐步融合&#xff0c;形成了一种新型的通讯方式——开疆智能MODBUS TCP转CANopen网关KJ-TCPC-CANP…...

Python爬虫(二):爬虫完整流程

爬虫完整流程详解&#xff08;7大核心步骤实战技巧&#xff09; 一、爬虫完整工作流程 以下是爬虫开发的完整流程&#xff0c;我将结合具体技术点和实战经验展开说明&#xff1a; 1. 目标分析与前期准备 网站技术分析&#xff1a; 使用浏览器开发者工具&#xff08;F12&…...

【RockeMQ】第2节|RocketMQ快速实战以及核⼼概念详解(二)

升级Dledger高可用集群 一、主从架构的不足与Dledger的定位 主从架构缺陷 数据备份依赖Slave节点&#xff0c;但无自动故障转移能力&#xff0c;Master宕机后需人工切换&#xff0c;期间消息可能无法读取。Slave仅存储数据&#xff0c;无法主动升级为Master响应请求&#xff…...

全志A40i android7.1 调试信息打印串口由uart0改为uart3

一&#xff0c;概述 1. 目的 将调试信息打印串口由uart0改为uart3。 2. 版本信息 Uboot版本&#xff1a;2014.07&#xff1b; Kernel版本&#xff1a;Linux-3.10&#xff1b; 二&#xff0c;Uboot 1. sys_config.fex改动 使能uart3(TX:PH00 RX:PH01)&#xff0c;并让boo…...

Springboot社区养老保险系统小程序

一、前言 随着我国经济迅速发展&#xff0c;人们对手机的需求越来越大&#xff0c;各种手机软件也都在被广泛应用&#xff0c;但是对于手机进行数据信息管理&#xff0c;对于手机的各种软件也是备受用户的喜爱&#xff0c;社区养老保险系统小程序被用户普遍使用&#xff0c;为方…...