千家信息网

Js实现Bind的使用方法

发表于:2026-10-31 作者:千家信息网编辑
千家信息网最后更新 2026年10月31日,这篇文章给大家介绍Js实现Bind的使用方法,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。最近在帮女朋友复习 JS 相关的基础知识,遇到不会的问题,她就会来问我。这不是很简单?三
千家信息网最后更新 2026年10月31日Js实现Bind的使用方法

这篇文章给大家介绍Js实现Bind的使用方法,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。

最近在帮女朋友复习 JS 相关的基础知识,遇到不会的问题,她就会来问我。

这不是很简单?三下五除二,分分钟解决。

function bind(fn, obj, ...arr) {  return fn.apply(obj, arr) }

于是我就将这段代码发了过去

这时候立马被女朋友进行了一连串的灵魂拷问。

这个时候,我马老师就坐不住了,我不服气,我就去复习了一下 bind,发现太久不写基础代码,还是会需要一点时间复习,这一次我得写一个有深度的 bind,深得马老师的真传,给他分成了五层速记法。

第一层 - 绑定在原型上的方法

这一层非常的简单,得益于 JS 原型链的特性。由于 function xxx 的原型链 指向的是 Function.prototype , 因此我们在调用 xxx.bind 的时候,调用的是 Function.prototype 上的方法。

Function.prototype._bind = function() {}

这样,我们就可以在一个构造函数上直接调用我们的bind方法啦~例如像这样。

funciton myfun(){} myfun._bind();

想要详细理解这方面的可以看这张图和这篇文章(https://github.com/mqyqingfeng/blog/issues/2)

第二层 - 改变 this 的指向

这可以说是 bind 最核心的特性了,就是改变 this 的指向,并且返回一个函数。而改变 this , 我们可以通过已知的 apply 和 call 来实现,这里我们就暂且使用 apply 来进行模拟。首先通过 self 来保存当前 this,也就是传入的函数。因为我们知道 this 具有 隐式绑定的规则(摘自 《你不知道的JavaScript(上)》2.2.2 ),

function foo() {console.log(this.a)} var obj = {a: 2, foo}; obj.foo(); // 2

通过以上特性,我们就可以来写我们的 _bind 函数。

Function.prototype._bind = function(thisObj) {  const self = this;  return function () {     self.apply(thisObj);   } } var obj = {a:1} function myname() {console.log(this.a)} myname._bind(obj)(); // 1

可能很多朋友都止步于此了,因为在一般的面试中,特别是一些校招面试中,可能你只需要知道前面两个就差不多了。但是想要在面试中惊艳所有人,仍然是不够的,接下来我们继续我们的探索与研究。

第三层 - 支持柯里化

函数柯里化是一个老生常谈的话题,在这里再复习一下。

function fn(x) {  return function (y) {   return x + y;  } } var fn1 = fn(1); fn1(2) // 3

不难发现,柯里化使用了闭包,当我们执行 fn1 的时候,函数内使用了外层函数的 x, 从而形成了闭包。

而我们的 bind 函数也是类似,我们通过获取当前外部函数的 arguments ,并且去除了绑定的对象,保存成变量 args,最后 return 的方法,再一次获取当前函数的 arguments, 最终用 finalArgs 进行了一次合并。

Function.prototype._bind = function(thisObj) {  const self = this;   const args = [...arguments].slice(1)  return function () {     const finalArgs = [...args, ...arguments]     self.apply(thisObj, finalArgs);   } }

通过以上代码,让我们 bind 方法,越来越健壮了。

var obj = { i: 1} function myFun(a, b, c) {   console.log(this.i + a + b + c); } var myFun1 = myFun._bind(obj, 1, 2); myFun1(3); // 7

一般到了这层,可以说非常棒了,但是再坚持一下下,就变成了完美的答卷。

第四层 - 考虑 new 的调用

要知道,我们的方法,通过 bind 绑定之后,依然是可以通过 new 来进行实例化的, new 的优先级会高于 bind(摘自 《你不知道的JavaScript(上)》2.3 优先级)。

这一点我们通过原生 bind 和我们第四层的 _bind 来进行验证对比。

// 原生 var obj = { i: 1} function myFun(a, b, c) {   // 此处用new方法,this指向的是当前函数 myFun    console.log(this.i + a + b + c); } var myFun1 = myFun.bind(obj, 1, 2); new myFun1(3); // NAN  // 第四层的 bind var obj = { i: 1} function myFun(a, b, c) {   console.log(this.i + a + b + c); } var myFun1 = myFun._bind(obj, 1, 2); new myFun1(3); // 7

注意,这里使用的是 bind方法

因此我们需要在 bind 内部,对 new 的进行处理。而 new.target 属性,正好是用来检测构造方法是否是通过 new 运算符来被调用的。

接下来我们还需要自己实现一个 new ,

而根据 MDN,new 关键字会进行如下的操作:

1.创建一个空的简单JavaScript对象(即{});

2.链接该对象(设置该对象的constructor)到另一个对象 ;

3.将步骤1新创建的对象作为this的上下文 ;

4.如果该函数没有返回对象,则返回this。

Function.prototype._bind = function(thisObj) {  const self = this;   const args = [...arguments].slice(1);  return function () {     const finalArgs = [...args, ...arguments];   // new.target 用来检测是否是被 new 调用     if(new.target !== undefined) {       // this 指向的为构造函数本身       var result = self.apply(this, finalArgs);       // 判断改函数是否返回对象       if(result instanceof Object) {         return reuslt;       }       // 没有返回对象就返回 this       return this;     } else {       // 如果不是 new 就原来的逻辑       return self.apply(thisArg, finalArgs);     }   } }

看到这里,你的造诣已经如火纯情了,但是最后还有一个小细节。

第五层 - 保留函数原型

以上的方法在大部分的场景下都没有什么问题了,但是,当我们的构造函数有 prototype 属性的时候,就出问题啦。因此我们需要给 prototype 补上,还有就是调用对象必须为函数。

Function.prototype._bind = function (thisObj) {   // 判断是否为函数调用   if (typeof target !== 'function' || Object.prototype.toString.call(target) !== '[object Function]') {     throw new TypeError(this + ' must be a function');   }   const self = this;   const args = [...arguments].slice(1);   var bound = function () {     var finalArgs = [...args, ...arguments];     // new.target 用来检测是否是被 new 调用     if (new.target !== undefined) {       // 说明是用new来调用的       var result = self.apply(this, finalArgs);       if (result instanceof Object) {         return result;       }       return this;     } else {       return self.apply(thisArg, finalArgs);     }   };   if (self.prototype) {     // 为什么使用了 Object.create? 因为我们要防止,bound.prototype 的修改而导致self.prototype 被修改。不要写成 bound.prototype = self.prototype; 这样可能会导致原函数的原型被修改。     bound.prototype = Object.create(self.prototype);     bound.prototype.constructor = self;   }   return bound; };

关于Js实现Bind的使用方法就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

函数 方法 对象 原型 指向 时候 复习 代码 特性 问题 柯里 检测 使用方法 接下来 优先级 内容 可以通过 基础 女朋友 就是 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 湖北九亚互联网络科技有限公司 互联网科技工作委员会主任 中关村互联网 科技集团 互联网科技公司华为 互联网科技官网 万达互联网科技 互联网科技大会 成都仁贤领冠互联网科技有限公司 恒生科技互联网指数分析 岳阳华臻互联网科技有限公司 中国互联网十大科技股排名 互联网保险科技创业 威龙国际互联网科技公司 世界互联网领先科技成果获奖 群盈汇互联网科技有限公司 众安科技工业互联网合作 扫呗互联网科技有限公司 互联网科技接地气 互联网科技创新创业项目 互联网金融金融科技 互联网是第几次科技革命的成果 广州大一互联网络科技有限公司 郑州华宇互联网科技 互联网科技公司招聘 深圳前海聚择互联网科技有限公司 互联网科技扶贫时间 国大互联网教育科技有限公司工作 明优互联网科技有限公司 华人运通互联网科技公司 广东猫王互联网科技有限公司电话
0