当前位置:网站首页>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
}
边栏推荐
- Unexpected ‘debugger‘ statement no-debugger
- [Junzheng T31] decompression and packaging of read-only rootfs file system squashfs
- Viewing splitchunks code segmentation from MPX resource construction optimization
- C binary tree structure definition and node value addition
- [JUC series] ThreadLocal of synchronization tool class
- Kyligence Zen, an intelligent indicator driven management and decision-making platform, is newly launched and is in limited internal testing
- C # implements definition, insertion and construction of binary sort tree
- How to fix ORA-01017:用户名/口令无效 登录拒绝
- Beifu controls the third-party servo to follow CSV mode -- Taking Huichuan servo as an example
- Install the typescript environment and enable vscode to automatically monitor the compiled TS file as a JS file
猜你喜欢

推荐模型复现(四):多任务模型ESMM、MMOE

Unexpected ‘debugger‘ statement no-debugger

Introduction to multi project development - business scenario Association basic introduction test payroll

Method area of JVM

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

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

LeetCode_双指针_中等_328.奇偶链表
![[leetcode] 14. Longest public prefix](/img/3b/3388ce8382ad5caaaf0a42488da2f9.png)
[leetcode] 14. Longest public prefix

ArcGIS中对面状河流进行等距分段【渐变赋色、污染物扩散】

1. opencv realizes simple color recognition
随机推荐
C # output the middle order traversal through the clue binary tree
Method area of JVM
How can colleges and universities build future oriented smart campus based on cloud native? Full stack cloud native architecture vs traditional IT architecture
倍福TwinCAT配置、调试第三方伺服详细讲解--以汇川IS620N为例子
[环境配置]PWC-Net
如何計算win/tai/loss in paired t-test
[environment configuration]pwc-net
Golang image/png 处理图片 旋转 写入
NvtBack
NvtBack
Uncover the practice of Baidu intelligent test in the field of automatic test execution
C # realize the definition, stack entry and stack exit of stack structure
Go learning - build a development environment vscode development environment golang
Murphy safety was selected for signing 24 key projects of Zhongguancun Science City
MIT linear algebra Chinese Notes
C # implements the operations of sequence table definition, insertion, deletion and search
Quick look | the long-awaited 2022 Guangzhou assistant testing engineer's real problem analysis is finally released
SCHIEDERWERK电源维修SMPS12/50 PFC3800解析
QT custom control: value range
倍福控制第三方伺服走CSV模式--以汇川伺服为例