当前位置:网站首页>bind原理及模拟实现
bind原理及模拟实现
2022-06-29 12:10:00 【Henry_楠】
前言
如果不了解bind的使用的请前往 Function.prototype.bind,这里不在赘述。
想要看bind原理的童鞋,需要对以下知识有了解:
思路
bind方法不会立即执行函数,而且需要保存一个入参,所以这里利用到了 闭包- 改变函数的作用域,因此要利用
apply或者call方法来实现 - 获取函数的所有入参
arguments,以及使用slice转化出一个数组
先利用上面的思路实现一个大致雏形的实现代码:
Function.prototype.mybind = function () {
if (typeof this !== 'function') throw 'Bind must be called on a function'
let _this = this, //这里的this是原函数
context = arguments[0],//获取要this指向的对象
slice = Array.prototype.slice,
args = slice.call(arguments, 1);//获取bind函数除this指向对象外的所有参数
//返回函数
return function () {
args = args.concat(slice.call(arguments))//合并bind的入参和执行时的入参
return _this.apply(context, args)
}
}
此时我们可以测试一下:
function test(a, b) {
console.log('this.name', this.name)
console.log('a', a)
console.log('b', b)
return str
}
const henry = {
name: 'henry',
}
// test.bind(henry, 1)(2, 3)
test.mybind(henry, 1)(2, 3)
好了,到此我们实现了bind的基础用法,但是还没完,假如我们用bind返回的函数当构造函数new一个对象会怎样呢?
原型链
官方文档 上有一段话:
A bound function may also be constructed using the new operator: doing so acts as though the target function had instead been constructed. The provided this value is ignored, while prepended arguments are provided to the emulated function.
意思就是说绑定函数也可以使用new操作符创建实例,这样做的行为就像是构造了目标函数一样,提供的this将被忽略,而前置参数还会参与使用。
- 我们要让实例的构造函数是目标函数
- 检测绑定函数的
this是否是目标函数的实例,是的话则忽略绑定时提供的this
...
context = this instanceof _this ? this : context
...
fn.prototype = _this.prototype
完整的代码是:
Function.prototype.mybind = function () {
if (typeof this !== 'function') throw 'Bind must be called on a function'
let _this = this,
context = arguments[0],//获取要this指向的对象
slice = Array.prototype.slice,
args = slice.call(arguments, 1);//获取bind函数除this指向对象外的所有参数
//返回函数
const fn = function () {
args = args.concat(slice.call(arguments))//合并bind的入参和执行时的入参
context = this instanceof _this ? this : context //如果this指向的对象的构造函数是原函数,则说明this是new过程中产生的对象,此时忽略绑定时提供的context
return _this.apply(context, args)
}
fn.prototype = _this.prototype
return fn
}
测试一下:
function test() {
}
const testBind = test.mybind()
const tb = new testBind()
console.log('tb', tb.constructor) //tb ƒ test() {}
好像到这来都没问题了,那我们来看看下面代码执行的结果
function test() {
}
const testBind = test.mybind()
const tb = new testBind()
testBind.prototype.say = function () {
console.log('say testBind')
}
test.prototype.say = function () {
console.log('say test')
}
tb.say() //say test
这不符合bind使用new的结果,结果应该是say testBind才对,这是因为绑定函数和构造函数的原型对象是同一个,所以我们这里应该用Object.create优化一下,完整代码如下:
Function.prototype.mybind = function () {
if (typeof this !== 'function') throw 'Bind must be called on a function'
let _this = this,
context = arguments[0],//获取要this指向的对象
slice = Array.prototype.slice,
args = slice.call(arguments, 1);//获取bind函数除this指向对象外的所有参数
//返回函数
const fn = function () {
args = args.concat(slice.call(arguments))//合并bind的入参和执行时的入参
context = this instanceof _this ? this : context //如果this指向的对象的构造函数是原函数,则说明this是new过程中产生的对象,此时忽略绑定时提供的context
return _this.apply(context, args)
}
fn.prototype = Object.create(_this.prototype)
return fn
}
边栏推荐
- Interview shock 61: tell me about MySQL transaction isolation level?
- C # implements definition, insertion and construction of binary sort tree
- Golang image/png 处理图片 旋转 写入
- Nacos startup error
- C # realize the hierarchical traversal of binary tree
- Recurrence of recommended models (III): recall models youtubednn and DSSM
- Lm07 - detailed discussion on cross section strategy of futures
- huffman编码
- async原理实现
- Uncover the practice of Baidu intelligent test in the field of automatic test execution
猜你喜欢
![[JUC series] ThreadLocal of synchronization tool class](/img/15/2f8ce68b9e5ee8dab03fb688712935.png)
[JUC series] ThreadLocal of synchronization tool class

缓存一致性,删除缓存,写入缓存,缓存击穿,缓存穿透,缓存雪崩

SCHIEDERWERK电源维修SMPS12/50 PFC3800解析

Interview shock 61: tell me about MySQL transaction isolation level?

如何計算win/tai/loss in paired t-test

qt 自定义控件 :取值范围

Beifu PLC controls servo through CANopen communication

QT custom control: value range
![[leetcode] 14. Longest public prefix](/img/3b/3388ce8382ad5caaaf0a42488da2f9.png)
[leetcode] 14. Longest public prefix

Uncover the practice of Baidu intelligent test in the field of automatic test execution
随机推荐
Can software related inventions be patented in India?
Interview shock 61: tell me about MySQL transaction isolation level?
C # realize the definition, stack entry and stack exit of stack structure
Proteus软件初学笔记
Understanding of P value
Qt的信号与槽
535. encryption and decryption of tinyurl: design a URL simplification system
Precautions for Beifu controller connecting Panasonic EtherCAT servo
Principle and process of MySQL master-slave replication
C#通过线索二叉树进行中序遍历输出
多项目开发入门-业务场景关联基础入门测试 工资表
推荐模型复现(一):熟悉Torch-RecHub框架与使用
Install the typescript environment and enable vscode to automatically monitor the compiled TS file as a JS file
如果我在深圳,到哪里开户比较好?另外想问,现在在线开户安全么?
C#实现堆栈结构的定义、入栈、出栈
Baidu cloud disk downloads large files without speed limit (valid for 2021-11 personal test)
Interview shock 61: tell me about MySQL transaction isolation level?
1. Opencv实现简单颜色识别
C#通过中序遍历对二叉树进行线索化
C # realize the hierarchical traversal of binary tree