JS手写-this绑定实现
在 JavaScript 中,bind、call 和 apply 方法都可以用来改变函数的 this 指向。下面我们将分别实现这些方法的简单版本。
1. 实现 bind
bind 方法创建一个新的函数,在调用时设置 this 值,并返回这个新的函数。
Function.prototype.myBind = function (context) {if (typeof this !== 'function') {throw new TypeError('Not a function');}const fn = this;const args = Array.prototype.slice.call(arguments, 1);return function bound() {const boundArgs = Array.prototype.slice.call(arguments);return fn.apply(context, args.concat(boundArgs));};
};
2. 实现 call
call 方法立即调用函数,并设置 this 值,同时传递参数列表。
Function.prototype.myCall = function (context) {if (typeof this !== 'function') {throw new TypeError('Not a function');}context = context || window;const args = Array.prototype.slice.call(arguments, 1);context.fn = this;const result = context.fn(...args);delete context.fn;return result;
};
3. 实现 apply
apply 方法与 call 类似,但传递的参数是一个数组。
Function.prototype.myApply = function (context, args) {if (typeof this !== 'function') {throw new TypeError('Not a function');}context = context || window;args = args || [];context.fn = this;const result = context.fn(...args);delete context.fn;return result;
};
示例代码
下面是一个完整的示例,展示了如何使用这些自定义的方法:
<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>自定义 bind, call, apply</title>
</head>
<body><script type="text/javascript">Function.prototype.myBind = function (context) {if (typeof this !== 'function') {throw new TypeError('Not a function');}const fn = this;const args = Array.prototype.slice.call(arguments, 1);return function bound() {const boundArgs = Array.prototype.slice.call(arguments);return fn.apply(context, args.concat(boundArgs));};};Function.prototype.myCall = function (context) {if (typeof this !== 'function') {throw new TypeError('Not a function');}context = context || window;const args = Array.prototype.slice.call(arguments, 1);context.fn = this;const result = context.fn(...args);delete context.fn;return result;};Function.prototype.myApply = function (context, args) {if (typeof this !== 'function') {throw new TypeError('Not a function');}context = context || window;args = args || [];context.fn = this;const result = context.fn(...args);delete context.fn;return result;};// 测试对象const obj = {name: '牛客网'};// 测试函数function greet(message) {console.log(`${message}, ${this.name}`);}// 使用 myBindconst greetBound = greet.myBind(obj, '欢迎来到');greetBound(); // 输出: 欢迎来到, 牛客网// 使用 myCallgreet.myCall(obj, '欢迎来到'); // 输出: 欢迎来到, 牛客网// 使用 myApplygreet.myApply(obj, ['欢迎来到']); // 输出: 欢迎来到, 牛客网</script>
</body>
</html>
详细步骤
-
实现
myBind:- 检查调用者是否为函数。
- 获取上下文
context和传入的参数args。 - 返回一个新的函数
bound,在调用时使用apply方法设置this值并传递参数。
-
实现
myCall:- 检查调用者是否为函数。
- 获取上下文
context和传入的参数args。 - 将函数赋值给
context的一个临时属性fn,调用该属性并传递参数,然后删除该属性。
-
实现
myApply:- 检查调用者是否为函数。
- 获取上下文
context和传入的参数数组args。 - 将函数赋值给
context的一个临时属性fn,调用该属性并传递参数,然后删除该属性。
测试
-
使用
myBind:- 创建一个绑定了
obj上下文的新函数greetBound,并调用它。
- 创建一个绑定了
-
使用
myCall:- 直接调用
greet函数,并设置obj为this值。
- 直接调用
-
使用
myApply:- 直接调用
greet函数,并设置obj为this值,参数以数组形式传递。
- 直接调用
相关文章:
JS手写-this绑定实现
在 JavaScript 中,bind、call 和 apply 方法都可以用来改变函数的 this 指向。下面我们将分别实现这些方法的简单版本。 1. 实现 bind bind 方法创建一个新的函数,在调用时设置 this 值,并返回这个新的函数。 Function.prototype.myBind …...
【时间之外】IT人求职和创业应知【31】
目录 新闻一:2024年“秦创原沣东杯”陕西省科技工作者创新创业大赛颁奖仪式暨沣东新城机器人产业发展大会盛大启幕 新闻二:声网CEO赵斌:RTE将成为生成式AI时代AI Infra的关键部分 新闻三:“5G工业互联网”融合应用试点城市名单…...
如何使用ffmpeg命令行进行录屏
录屏软件,我们去网上下载,发现有很多软件都是要收费的!但是录屏功能很难做吗?为啥都需要收费呢? 于是我整了个小demo,用于实现基础的屏幕录制功能。 思路很简单,考虑到 FFMpeg.exe是一个非常成…...
ODOO学习笔记(8):模块化架构的优势
灵活性与可定制性 业务流程适配:企业的业务流程往往因行业、规模和管理方式等因素而各不相同。Odoo的模块化架构允许企业根据自身的具体业务流程,选择和组合不同的模块。例如,一家制造企业可以启用采购、库存、生产和销售模块,并通…...
数字IC后端实现之Innovus specifyCellEdgeSpacing和ICC2 set_placement_spacing_rule的应用
昨天帮助社区IC训练营学员远程协助解决一个Calibre DRC案例。通过这个DRC Violation向大家分享下Innovus和ICC2中如何批量约束cell的spacing rule。 数字IC后端手把手实战教程 | Innovus verify_drc VIA1 DRC Violation解析及脚本自动化修复方案 下图所示为T12nm A55项目的Ca…...
每日小练:Day2
1.乒乓球筐 题目链接:乒乓球筐__牛客网 题目描述: 这道题主要考察B盒是不是A盒的子集,我们可以通过哈希表来做 单哈希表 import java.util.Scanner;// 注意类名必须为 Main, 不要有任何 package xxx 信息 public class Main {public stat…...
ubuntu 安装kafka-eagle
上传压缩包 kafka-eagle-bin-2.0.8.tar.gz 到集群 /root/efak 目录 cd /root/efak tar -zxvf kafka-eagle-bin-2.0.8.tar.gz cd /root/efak/kafka-eagle-bin-2.0.8 mkdir /root/efakmodule tar -zxvf efak-web-2.0.8-bin.tar.gz -C /root/efakmodule/ mv /root/efakmodule/efak…...
深入理解指针
在初步了解了指针的用法之后,我们可以想一想,既然一个变量有地址,而且在上一篇文章中我们知道了一个数组也有地址,那么函数、字符串这些东西有没有地址呢?如果有,那这些地址有什么用?我们又要怎…...
自动驾驶合集(更新中)
文章目录 车辆模型控制路径规划 车辆模型 车辆模型基础合集 控制 控制合集 路径规划 规划合集...
Chapter 14 scoped样式以及data函数
欢迎大家订阅【Vue2Vue3】入门到实践 专栏,开启你的 Vue 学习之旅! 文章目录 1 scoped样式1.1 全局样式1.2 局部样式1.3 工作原理2 data函数 1 scoped样式 1.1 全局样式 全局样式是指作用于整个应用程序的样式,不论在哪个组件中定义&#x…...
Golang | Leetcode Golang题解之第557题反转字符串中的单词III
题目: 题解: func reverseWords(s string) string {length : len(s)ret : []byte{}for i : 0; i < length; {start : ifor i < length && s[i] ! {i}for p : start; p < i; p {ret append(ret, s[start i - 1 - p])}for i < le…...
区块链技术在电子政务中的应用
💓 博客主页:瑕疵的CSDN主页 📝 Gitee主页:瑕疵的gitee主页 ⏩ 文章专栏:《热点资讯》 区块链技术在电子政务中的应用 区块链技术在电子政务中的应用 区块链技术在电子政务中的应用 引言 区块链技术概述 定义与原理 发…...
Simulink中Matlab function使用全局变量
目录 一. 引言二. 普通Matlab function使用全局变量三. Simulink中的Matlab function使用全局变量四. 如何利用Matlab function的全局变量施加随机噪声 一. 引言 最近发现了之前仿真中的一个问题,记录一下备忘。 Matlab function中有时候需要用到全局变量…...
WPF-控件的属性值的类型转化
控件的属性值需要转成int、double进行运算的,可以使用一下方法 页面代码 <StackPanel Margin"4,0,0,0" Style"{StaticResource Form-StackPanel}"> <Label Content"替换后材料增加金额ÿ…...
海思Hi3516DV300上播放G711U音频文件
在海思Hi3516DV300芯片运行Linux系统下,可通过如下函数来实现G711U音频文件的播放: int ADecPlayVoiceFile(const char* filename) {FILE* pfd;AUDIO_STREAM_S stStream;HI_S32 s32Ret,length,decLength,allLength 0,aChn 0;HI_U8 buf[SAMPLE_AUDIO_P…...
Linux源码阅读笔记-V4L2框架基础介绍
V4L2视频设备驱动基础 V4L2 是专门为 Linux 设备设计的整套视频框架(其主要核心在 Linux 内核,相当于 Linux 操作系统上层的视频源捕获驱动框架)。为上层访问系统底层的视频设备提供一个统一的标准接口。V4L2 驱动框架能够支持多种类型设备&…...
列表(list)
一、前言 本次博客主要讲解 list 容器的基本操作、常用接口做一个系统的整理,结合具体案例熟悉自定义内部排序方法的使用。如有任何错误,欢迎在评论区指出,我会积极改正。 二、什么是list list是C的一个序列容器,插入和删除元素…...
使用Python抓取数据的实战指南
引言 在当今信息爆炸的时代,数据已成为一种宝贵的资源。无论是学术研究、市场分析,还是个人兴趣,数据的获取都是至关重要的一步。Python,凭借其强大的库和简洁的语法,成为了数据抓取(也称为网络爬虫或网页…...
GIC寄存器介绍
往期内容 本专栏往期内容,interrtupr子系统: 深入解析Linux内核中断管理:从IRQ描述符到irq domain的设计与实现Linux内核中IRQ Domain的结构、操作及映射机制详解中断描述符irq_desc成员详解Linux 内核中断描述符 (irq_desc) 的初始化与动态分…...
c++实现B树(下)
书接上回小吉讲的是B树的搭建和新增方法的实现(blog传送门🚪:B树实现上)(如果有小可爱对B树还不是很了解的话,可以先看完上一篇blog,再来看小吉的这篇blog)。那这一篇主要讲的是B树中…...
Oni-Duplicity:轻松定制《缺氧》游戏体验,告别资源与角色困扰
Oni-Duplicity:轻松定制《缺氧》游戏体验,告别资源与角色困扰 【免费下载链接】oni-duplicity A web-hosted, locally-running save editor for Oxygen Not Included. 项目地址: https://gitcode.com/gh_mirrors/on/oni-duplicity 你是否曾在《缺…...
轻量级跨平台桌面应用开发:Tauri零门槛实战指南
轻量级跨平台桌面应用开发:Tauri零门槛实战指南 【免费下载链接】tauri Build smaller, faster, and more secure desktop and mobile applications with a web frontend. 项目地址: https://gitcode.com/GitHub_Trending/ta/tauri 在桌面应用开发领域&#…...
MMSkeleton部署指南:从开发环境到生产环境的完整迁移
MMSkeleton部署指南:从开发环境到生产环境的完整迁移 【免费下载链接】mmskeleton A OpenMMLAB toolbox for human pose estimation, skeleton-based action recognition, and action synthesis. 项目地址: https://gitcode.com/gh_mirrors/mm/mmskeleton MM…...
如何用Win11Debloat让你的Windows系统速度提升70%:终极优化指南
如何用Win11Debloat让你的Windows系统速度提升70%:终极优化指南 【免费下载链接】Win11Debloat A simple, lightweight PowerShell script that allows you to remove pre-installed apps, disable telemetry, as well as perform various other changes to declutt…...
Apache HBase与Spark集成终极指南:10个实时数据处理高效方案
Apache HBase与Spark集成终极指南:10个实时数据处理高效方案 【免费下载链接】hbase Apache HBase 项目地址: https://gitcode.com/GitHub_Trending/hb/hbase Apache HBase是一个高可靠性、高性能、面向列的分布式存储系统,非常适合存储海量结构化…...
Leaflet图层顺序实战:如何用setZIndex和bringToFront让你的地图层级不再混乱
Leaflet图层顺序实战:如何用setZIndex和bringToFront让你的地图层级不再混乱 当地图上同时存在多个图层时,你是否遇到过标注被底图遮盖、动态添加的标记消失在多边形下方,或是图层叠加顺序完全失控的情况?这些看似简单的层级问题&…...
StructBERT中文情感WebUI多语言支持:中英双语界面切换与结果输出
StructBERT中文情感WebUI多语言支持:中英双语界面切换与结果输出 1. 项目介绍与核心价值 如果你正在寻找一个能快速上手、效果不错的中文情感分析工具,那么今天介绍的StructBERT中文情感分析WebUI,可能就是你的理想选择。这个项目基于百度开…...
构建智能体的专业技能树 - Agent Skills生态全析(中篇)
一、概述 这篇文章我们将围绕Skills、Tools、MCP、Subagents 四个组件有什么区别、Anthropic 官方做好了哪些现成 Skills、如何从零创建一个自定义 Skill 的完整流程 这些四个方面来进行讲解。 二、智能体生态系统概览 在 Anthropic 构建的智能体生态中,多种技术组件…...
CVE-2024-36401复现
一.漏洞概述 CVE-2024-36401 是 GeoServer 中的一个严重级远程代码执行漏洞(CVSS 9.8),允许未经身份验证的远程攻击者在服务器上执行任意代码。该漏洞源于 GeoServer 调用的 GeoTools 库 API 在评估 XPath 表达式时存在不安全处理࿰…...
视频号推客模式系统小程序开发
开发一个基于微信视频号的推客模式系统小程序,需要结合微信生态的开放能力和推客(分销)模式的业务逻辑。以下是关键开发要点:微信小程序与视频号打通通过微信开放平台的JS-SDK实现小程序与视频号的互联互通。调用wx.openChannelsA…...
