面试官:能用JavaScript手写一个bind函数吗
经常会看到网上各种手写bind的教程,下面是我在自己实现手写bind的过程中遇到的问题与思考。如果对于如何实现一个手写bind还有疑惑的话,那么可以先看看上面两篇文章。
手写bind vs 原生bind
我们先使用一个典型的手写bind的例子,代码如下:
Function.prototype.bind2 = function (context) {if (typeof this !== "function") {throw new Error("Function.prototype.bind - what is trying to be bound is not callable");}var self = this;var args = Array.prototype.slice.call(arguments, 1);var fNOP = function () {};var fBound = function () {var bindArgs = Array.prototype.slice.call(arguments);return self.apply(this instanceof fNOP ? this : context, args.concat(bindArgs));}fNOP.prototype = this.prototype;fBound.prototype = new fNOP();return fBound;
}
我们首先用原生bind运行一下代码
function Foo(a) {this.a = a}
Foo.prototype.sayHi = function( ) {}
let _Foo = Foo.bind(undefined, 'a')
new _Foo()

然后使用手写版代码,运行同样的代码
function Foo(a) {this.a = a}
Foo.prototype.sayHi = function( ) {}
let _Foo = Foo.bind2(undefined, 'a')
new _Foo()

我们可以看到相比原生bind方法,手写版的bind方法返回的构造函数,构造出来的新对象会比原生的多一层__proto__。而这个__proto__产生的原因就是在很多教程中提到的防止原型链篡改。
这也就是为什么很多的文章会告诉你,为什么要添加下面的代码。
var fNOP = function () {};
fNOP.prototype = this.prototype;
fBound.prototype = new fNOP();
这段代码中,使用了一个空函数作为中转,相当于Object.create(fBound.prototype)。具体可以查看文章开头给出的文章,里面的详细的说明。
规范中的bind
既然说道,加上面的代码是为了防止原型链篡改。我就想看看原生的bind如何处理这个问题的呢?参考 前端进阶面试题详细解答
function Foo(a) {this.a = a}
Foo.prototype.sayHi = function( ) {}
let _Foo = Foo.bind(undefined, 'a')
_Foo.prototype.sayHi = function( ) {console.log('篡改的_Foo的sayHi方法')}
(new _Foo().sayHi())
我发现在运行上面的代码,程序执行到修改_Foo的原型方法的语句时,就已经报错了。提示表明_Foo没有prototype属性!既然没有prototype属性,那么是不是也就不用处理原型链篡改的问题了呢?
之后,我查了一下规范, 在NOTE中,有下面一段话。明确指出了bind返回的函数是没有prototype属性,这也多少印证了上面的猜想。
Function objects created using Function.prototype.bind do not have a prototype property or the [[Code]], [[FormalParameters]], and [[Scope]] internal properties.
其中需要注意的有一点是这条:
- Set the [[Prototype]] internal property of F to the standard built-in Function prototype object as specified in 15.3.3.1.
我自己理解的意思是是bind出来的函数对象的prototype属性是内建的Function.prototype属性, 这里应该是说明了为什么原生的bind不会多一层__proto__属性
小结
写这篇的目的是总结下自己在实现bind过程中遇到的问题,记录探究的过程。通过一系列手写原生方法,锻炼了我们对于原理的进一步认识。但是也要注意验证,实际去操作几次,可能得出自己的经验。如果有更多的两者对比的发现,可以在评论里告诉我,欢迎各位大佬斧正。
相关文章:
面试官:能用JavaScript手写一个bind函数吗
经常会看到网上各种手写bind的教程,下面是我在自己实现手写bind的过程中遇到的问题与思考。如果对于如何实现一个手写bind还有疑惑的话,那么可以先看看上面两篇文章。 手写bind vs 原生bind 我们先使用一个典型的手写bind的例子,代码如下&a…...
美国拟发布纽扣电池或硬币电池安全标准和通知要求ANSI C18. 3M
2023年2月10日,美国向WTO提交G/TBT/N/USA/1964号通报,拟发布纽扣电池或硬币电池以及含有此类电池的消费品的安全标准和通知要求,征求意见截止日期为2023年3月13日,拟通过日期和生效日期待定。联[1]系 拟定规则通知根据H.R.5313瑞…...
双因素方差分析
一、案例与数据 一家大型商业银行在多地区设有分行,其业务主要是进行基础设施建设,国家重点项目建设,固定资产投资等项目的贷款。近年来,该银行的贷款额平稳增长,但不良贷款额也有较大比例的提高,这给银行…...
[ vulhub漏洞复现篇 ] Drupal XSS漏洞 (CVE-2019-6341)
🍬 博主介绍 👨🎓 博主介绍:大家好,我是 _PowerShell ,很高兴认识大家~ ✨主攻领域:【渗透领域】【数据通信】 【通讯安全】 【web安全】【面试分析】 🎉点赞➕评论➕收藏 养成习…...
「TCG 规范解读」第8章 TPM工作组 TPM 1.2中 SHA1的使用
可信计算组织(Ttrusted Computing Group,TCG)是一个非盈利的工业标准组织,它的宗旨是加强在相异计算机平台上的计算环境的安全性。TCG于2003年春成立,并采纳了由可信计算平台联盟(the Trusted Computing Platform Alli…...
熵权法计算权重
文章目录1. 多属性决策问题2. 熵(entropy)3. 信息熵4. 熵权法5. 熵权法的实现基于信息论的熵值法是根据各指标所含信息有序程度的差异性来确定指标权重的客观赋权方法,仅依赖于数据本身的离散程度。熵用于度量不确定性,指标的离散…...
redis实现用户签到,统计活跃用户,用户在线状态,用户留存率
开发的过程中,可能会遇到用户签到、统计当天的活跃用户、以及每个用户的在线状态,用户留存率的开发需求,可能会用传统的方法,根据相应的需求设计数据库表等,但这样耗费的存储空间大,以及性能方面也不会太好…...
MySQL中有多少种索引?索引的底层实现原理
索引存储在内存中,为服务器存储引擎为了快速找到记录的一种数据结构。索引的主要作用是加快数据查找速度,提高数据库的性能。索引的分类(1) 普通索引:最基本的索引,它没有任何限制。(2) 唯一索引:与普通索引类似&#…...
LeetCode经典算法题:二叉树遍历(递归遍历+迭代遍历+层序遍历)以及线索二叉树java详解
LeetCode经典算法题:二叉树遍历(递归遍历迭代遍历层序遍历)以及线索二叉树java详解 文章目录二叉树遍历题目描述解题思路与代码递归遍历迭代遍历层序遍历线索二叉树:二叉树遍历 题目描述 从根节点往下查找,先找左子树…...
【Java闭关修炼】MyBatis-接口代理的方式实现Dao层
【Java闭关修炼】MyBatis-接口代理的方式实现Dao层实现规则代码实现代理对象分析接口代理方式小结实现规则 映射配置文件中的名称空间必须和Dao层接口的全类名相同映射配置文件的增删改查标签的id属性必须和Dao层接口方法的参数相同映射配置文件中的增删改查标签的parameterTyp…...
2022年网络安全政策态势分析与2023年立法趋势
近日,公安部第三研究所网络安全法律研究中心与 360 集团法务中心联合共同发布了《全球网络安全政策法律发展年度报告(2022)》。《报告》概览2022年全球网络安全形势与政策法律态势,并对2023年及后续短期内网络安全政策、立法趋势进…...
使用vmware制作云平台redhat7.9镜像模板
一、概述 1.1 redhat7.9 定制镜像上传到云平台。 这个制作镜像得方式适用于多种iso 镜像。 将iso 镜像通过vmware 创建出一台虚机,对虚机做一些基础配置。在虚机上安装kvm 虚拟化得工具, 将iso 镜像在导入虚机种通过kvm创建一下虚机, 虚机创…...
OpenCV基础(28)使用OpenCV进行摄像机标定Python和C++
摄像头是机器人、监控、太空探索、社交媒体、工业自动化甚至娱乐业等多个领域不可或缺的一部分。 对于许多应用,必须了解相机的参数才能有效地将其用作视觉传感器。 在这篇文章中,您将了解相机校准所涉及的步骤及其意义。 我们还共享 C 和 Python 代码以…...
APB总线详解及手撕代码
本文的参考资料为官方文档AMBA™3 APB Protocol specification文档下载地址: https://pan.baidu.com/s/1Vsj4RdyCLan6jE-quAsEuw?pwdw5bi 提取码:w5bi APB端口介绍介绍总线具体握手规则之前,需要先熟悉一下APB总线端口,APB的端口…...
【Linux/Windows】源文件乱码问题解决方法总结
🐚作者简介:花神庙码农(专注于Linux、WLAN、TCP/IP、Python等技术方向)🐳博客主页:花神庙码农 ,地址:https://blog.csdn.net/qxhgd🌐系列专栏:Linux技术&…...
Python 四大主流 Web 编程框架
目前Python的网络编程框架已经多达几十个,逐个学习它们显然不现实。但这些框架在系统架构和运行环境中有很多共通之处,本文带领读者学习基于Python网络框架开发的常用知识,及目前的4种主流Python网络框架:Django、Tornado、Flask、Twisted。 …...
学UI设计,可以向哪些方向发展?该怎么学?
1、什么是UI设计?UI设计,全称 User Interface,翻译成中文意思叫做用户界面设计。2、UI设计的类型UI设计按用户和界面来分可分成四种UI设计。分别是移动端UI设计,PC端UI设计,游戏UI设计,以及其它UI设计。第一…...
【C++】初识CC++内存管理
前言 我们都知道C&C是非常注重性能的语言,因此对于C&C的内存管理是每一个C/C学习者必须重点掌握的内容,本章我们并不是深入讲解C&C内存管理,而是介绍C&C内存管理的基础知识,为我们以后深入理解C&C内存管理做铺…...
Nacos快速使用指南
简单例子:springboot快速集成nacos官方github文档命名空间是绝对隔离的。group之间可以通过配置实现跨 group访问配置中心Nacos config官方文档应用级别的默认配置文件名(dataId)dataId 的完整格式如下:${prefix}-${spring.profil…...
复旦发布国内首个类ChatGPT模型MOSS,和《流浪地球》有关?
昨晚,复旦大学自然语言处理实验室邱锡鹏教授团队发布国内首个类ChatGPT模型MOSS,现已发布至公开平台https://moss.fastnlp.top/ ,邀公众参与内测。 MOSS和ChatGPT一样,开发的过程也包括自然语言模型的基座训练、理解人类意图的对…...
Java 8 Stream API 入门到实践详解
一、告别 for 循环! 传统痛点: Java 8 之前,集合操作离不开冗长的 for 循环和匿名类。例如,过滤列表中的偶数: List<Integer> list Arrays.asList(1, 2, 3, 4, 5); List<Integer> evens new ArrayList…...
STM32F4基本定时器使用和原理详解
STM32F4基本定时器使用和原理详解 前言如何确定定时器挂载在哪条时钟线上配置及使用方法参数配置PrescalerCounter ModeCounter Periodauto-reload preloadTrigger Event Selection 中断配置生成的代码及使用方法初始化代码基本定时器触发DCA或者ADC的代码讲解中断代码定时启动…...
现代密码学 | 椭圆曲线密码学—附py代码
Elliptic Curve Cryptography 椭圆曲线密码学(ECC)是一种基于有限域上椭圆曲线数学特性的公钥加密技术。其核心原理涉及椭圆曲线的代数性质、离散对数问题以及有限域上的运算。 椭圆曲线密码学是多种数字签名算法的基础,例如椭圆曲线数字签…...
scikit-learn机器学习
# 同时添加如下代码, 这样每次环境(kernel)启动的时候只要运行下方代码即可: # Also add the following code, # so that every time the environment (kernel) starts, # just run the following code: import sys sys.path.append(/home/aistudio/external-libraries)机…...
【网络安全】开源系统getshell漏洞挖掘
审计过程: 在入口文件admin/index.php中: 用户可以通过m,c,a等参数控制加载的文件和方法,在app/system/entrance.php中存在重点代码: 当M_TYPE system并且M_MODULE include时,会设置常量PATH_OWN_FILE为PATH_APP.M_T…...
wpf在image控件上快速显示内存图像
wpf在image控件上快速显示内存图像https://www.cnblogs.com/haodafeng/p/10431387.html 如果你在寻找能够快速在image控件刷新大图像(比如分辨率3000*3000的图像)的办法,尤其是想把内存中的裸数据(只有图像的数据,不包…...
倒装芯片凸点成型工艺
UBM(Under Bump Metallization)与Bump(焊球)形成工艺流程。我们可以将整张流程图分为三大阶段来理解: 🔧 一、UBM(Under Bump Metallization)工艺流程(黄色区域ÿ…...
Python的__call__ 方法
在 Python 中,__call__ 是一个特殊的魔术方法(magic method),它允许一个类的实例像函数一样被调用。当你在一个对象后面加上 () 并执行时(例如 obj()),Python 会自动调用该对象的 __call__ 方法…...
表单设计器拖拽对象时添加属性
背景:因为项目需要。自写设计器。遇到的坑在此记录 使用的拖拽组件时vuedraggable。下面放上局部示例截图。 坑1。draggable标签在拖拽时可以获取到被拖拽的对象属性定义 要使用 :clone, 而不是clone。我想应该是因为draggable标签比较特。另外在使用**:clone时要将…...
GitHub 常见高频问题与解决方案(实用手册)
1.Push 提示权限错误(Permission denied) 问题: Bash Permission denied (publickey) fatal: Could not read from remote repository. 原因: 没有配置 SSH key 或使用了 HTTPS 而没有权限…...
