千家信息网

怎么手写实现bind函数

发表于:2025-02-02 作者:千家信息网编辑
千家信息网最后更新 2025年02月02日,本篇内容介绍了"怎么手写实现bind函数"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!前面发了一篇文
千家信息网最后更新 2025年02月02日怎么手写实现bind函数

本篇内容介绍了"怎么手写实现bind函数"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

前面发了一篇文章,面试题目之原生实现call、apply、bind,这篇文章介绍了如何手动实现call、apply、bind,但是前不久重读这篇文章时发现了实现bind的代码不是很完善,我们看一段代码:

function Person(){  this.name="zs";  this.age=18;  this.gender="男"}var obj={  hobby:"看书"}//  将构造函数的this绑定为objvar changePerson = Person.bind(obj);//  直接调用构造函数,函数会操作obj对象,给其添加三个属性;changePerson();//  1、输出objconsole.log(obj);
// 用改变了this指向的构造函数,new一个实例出来var p = new changePerson();// 2、输出objconsole.log(p);

代码输出结果:

1、输出:

2、输出:

仔细观察上面的代码,再看输出结果。

我们对Person类使用了bind将其this指向obj,得到了changeperson函数,此处如果我们直接调用changeperson会改变obj,若用new调用changeperson会得到实例 p,并且其__proto__指向Person,我们发现bind失效了。

我们得到结论:用bind改变了this指向的函数,如果用new操作符来调用,bind将会失效。

再看我们这篇文章(面试题目之原生实现call、apply、bind)中bind实现的代码:


Function.prototype.myBind = function(ctx, ...argv1) { return (...argv2) => { return this.call(ctx, ...argv1, ...argv2) }}

如果看不太习惯,将其转化为es5的执行方式:

Function.prototype.mybind = function(){  // 1、保存函数  var _this = this;  // 2、保存目标对象  var context = arguments[0]||window;  // 3、保存目标对象之外的参数,将其转化为数组;  var rest = Array.prototype.slice.call(arguments,1);  // 4、返回一个待执行的函数  return function F(){  // 5、将二次传递的参数转化为数组;    var rest2 = Array.prototype.slice.call(arguments)    //6、用apply调用第一步保存的函数,并绑定this,传递合并的参数数组    _this.apply(context,rest.concat(rest2));  }}

我们用自己实现的mybind函数,来实现文章最上面的例子,测试一下如果,用mybind函数改变了构造函数的this,然后用new来执行生成的新函数,能否得到和原生bind一样的效果,测试代码如下:

function Person(){  this.name="zs";  this.age=18;  this.gender="男"}var obj={  hobby:"看书"}//  将构造函数的this绑定为obj ,此处调用上面开发的mybind方法;var changePerson = Person.mybind(obj);//  直接调用构造函数,函数会操作obj对象,给其添加三个属性;changePerson();//  1、输出objconsole.log(obj);
// 用改变了this指向的构造函数,new一个实例出来var p = new changePerson();// 2、输出objconsole.log(p);

查看输出结果:

1、输出:

2、输出:

我们用上面实现的mybind改变函数的this,然后调用new方法,发现并未实现和原生bind一样的效果,我们实现的mybind方法和原生的bind实现的功能还有些差距,那么我们如何修正呢?

仔细观察代码,发现突破点再这里: new changeperson()。

这里我们只需要在调用 new changeperson()时候,判断一下,是否是通过new操作符调用的,如果是new 操作符调用的话,我们就用new直接调用未改变this之前的函数,并返回其结果。

那么如何判断是否是通过new操作符来调用一个函数呢?这里我们就要用到instanceof了,看看官方文档对其解释:


| instanceof运算符用于测试构造函数的prototype属性是否出现在对象的

| 原型链中的任何位置。

翻译成大白话,就是判断某个实例是否由某个类或者构造函数生成。

回归正文,我们知道,我们在用new操作符调用一个构造函数时,或者普通函数,都会在函数内部执行如下步骤:

1、生成一个空对象,

2、然后将this指向这个空对象,

3、最后将这个对象返回。

而这个对象就是这个构造函数的实例,那么只要在函数内部执行 this instanceof 构造函数 来判断其结果是否为true,就能判断函数是否是通过new操作符来调用了,若结果为true则是用new操作符调用的,代码修正如下:

Function.prototype.mybind = function(){  // 1、保存函数  var _this = this;  // 2、保存目标对象  var context = arguments[0]||window;  // 3、保存目标对象之外的参数,将其转化为数组;  var rest = Array.prototype.slice.call(arguments,1);  // 4、返回一个待执行的函数  return function F(){     // 5、将二次传递的参数转化为数组;     var rest2 = Array.prototype.slice.call(arguments)    if(this instanceof F){      // 6、若是用new操作符调用,则直接用new 调用原函数,并用扩展运算符传递参数      return new _this(...rest2)    }else{           //7、用apply调用第一步保存的函数,并绑定this,传递合并的参数数组      _this.apply(context,rest.concat(rest2));    }  }}

此时,测试在运行上面的测试案例,打印结果为:

完美实现了和原生bind一样的效果,对一个知识点进行比较深入的研究确实不容易,越深入发现涉及的知识越广泛,就像这篇文章,虽然说得是bind的手动实现,但是其实涉及了new操作符调用的原理,instanceof 的用法。

"怎么手写实现bind函数"的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注网站,小编将为大家输出更多高质量的实用文章!

函数 输出 对象 操作符 代码 参数 结果 指向 数组 实例 篇文章 测试 目标 知识 属性 效果 方法 面的 生成 三个 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 郑州大学中原网络安全院 吴忠团市委网络安全宣传周 jsp连接数据库手机查询 温州计算机网络技术有哪些 属于文摘数据库的有哪些 软件开发成本属于什么需求 南阳软件开发税务筹划如何做 数据库空间怎么查看 创造与魔法拆家服务器名称 博途数据库快照 丽水互联网科技医院 数据库中的大整数数据类型 机顶盒刷成文件服务器 网络技术研究是弄什么的 sql 数据库实时同步 全球原料药数据库 cs起源连接安全服务器 数据库技术与应用笔试 京东物流软件开发师前景 天马时空网络技术有限公司在哪 郑州大学中原网络安全院 数据库混乱 app软件开发专业软件 我的世界网易版服务器有趣的指令 数据库技术主要用于什么领域 数据库学习心得体会1000字 哈尔滨市网络安全和信息化委员会 怎么组装云桌面服务器 分布式数据库系统的定义 山东安卓软件开发公司有哪些
0