bind 是在 ES5 加入的语法,具体如何使用 MDN 都有。但有一点需要额外注意一下:bind 会返回一个新的函数。也就是说:它会修改 this 的指向,并返回新的函数体。

接下来,我来讲一下手写 bind 的思路。

首先我们要明白 bind 的用途:它是为了改变默认 this 的,如:

var obj = { a: 1 }
function yyy(a) {this.a = a}
var xxx = yyy.bind(obj)
xxx(a) = 3
console.log(obj.a) // 3
复制代码

此时 xxx 的代码实际上是下面这样的

function xxx(newA) {obj.a = newA
}
复制代码

了解了如何使用,我们才能往下写,我们来为函数的原型添加一个 myBind 方法

(Function.prototype.myBind = function(otherThis) {// 当前的 this 是 yyy,如果 this 的类型不是函数,就返回if (typeof this !== 'function') {return}// 获取 yyy 除去第一项后的参数,也就是除去 this 的剩余参数var bindArgs = Array.prototype.slice.call(arguments, 1) var bindArgsLength = bindArgs.length  // 这句话很重要,代码后有解释var fBind = this // yyy ,也就是要绑定到哪里var fNP = function(){}  // 中间量,以便生成的 xxx 和原来函数毫无瓜葛var fBound = function() {bindArgs.length = bindArgsLength // 必须重置 bindArgs 的长度bindArgs.push.apply(bindArgs, arguments) // 组合两次的数据return fBind.apply(otherThis, bindArgs) // 用 apply 方法为新的返回值绑定用户指定的 this}if (this.prototype) { // Function.prototype 没有 prototypefNP.prototype = this.prototype}fBound.prototype = new fNP() return fBound
})()复制代码

需要说明一下重置 bindArgs 那一句话:

因为 bindArgs 是和 fBound 同一级别的,当执行 myBind 这个函数之后,fBound 和 bindArgs 都只有一份,但是可能多次调用 myBind 返回的函数(这里是 xxx)并传参,如果不重置,我们两次调用 xxx('aaa'),那 bindArgs 的长度就变为 2 了,但我们希望两次调用不能被影响,只能受父亲 yyy 传参的影响。由于每次添加都是 push 到后面,所有每次只要恢复成以前的长度即可。

好了,我们已经大致完成了,我们已经可以在函数种使用了。

但是还有一个缺陷:不支持 new,真正的 bind 方法在使用 new 之后的 this 还是指向 new 新生成的对象。

举例来说,我们希望得到下面的效果:

var obj = { a: 1 }
function yyy(a) {this.a = a}
var xxx = yyy.myBind(obj)
var xxxxxx = new xxx('你好')
console.log(obj.a) // 1
console.log(xxxxxx.a) // 你好
复制代码

而我们现在的代码是如何的呢? 由于我们没做判断,我们返回的函数实际还是:

function xxx(newA) {obj.a = newA
}
复制代码

结果是:xxxxxx.a 未定义,而 obj.a 是你好。

如何解决?只需在执行 apply 的时候绑定更换绑定的 this 就好了 解决的关键是 this 到底指向什么,如果使用 new 操作符,那个时候的 this 就是指向新的对象

(Function.prototype.myBind = function(otherThis) {// 当前的 this 是 yyy,如何 this 的类型不是函数,就返回if (typeof this !== 'function') {return}var bindArgs = Array.prototype.slice.call(arguments, 1) // 获取 yyy 除去第一项后的参数var bindArgsLength = bindArgs.length var fBind = this // yyy ,也是是要绑定到哪里var fNP = function(){}  // 中间量,以便生成的 xxx 和原来函数毫无瓜葛if (this.prototype) { // Function.prototype 没有 prototypefNP.prototype = this.prototype} // 放在前面便于理解var fBound = function() {bindArgs.length = bindArgsLength // 必须重置 bindArgs 的长度bindArgs.push.apply(bindArgs, arguments) // 组合两次的数据// 如果使用 new 操作符,此时 this 指向的是新生成的对象,那么 fNP.prototype.isPrototypeOf(this) === true// xxxxxx -> xxx -> FNPreturn fBind.apply( fNP.prototype.isPrototypeOf(this) ? this: otherThis, bindArgs) }fBound.prototype = new fNP() return fBound
})()
复制代码

写完了,昨天花了一个下午的时间在理解这个问题,我认为理解起来还是有点难度的,希望帮助到你。

(完)

转载于:https://juejin.im/post/5c7f68a8f265da2d97111a91

结合MDN的代码手写bind相关推荐

  1. 【bind()函数】JavaScript手写bind()及详解-超详细~~~

    这两天学习了手写call.apply.bind,手写bind思考了很久才实现了MDN的示例的结果,所以记录下来~ 因为是第一篇文章,所以可能存在一些错误,希望各位大佬批评指正,不吝赐教. 也欢迎不懂的 ...

  2. 全网最详细手写bind

    手写bind 在写代码前,一定要分析这个api或者关键字实现了什么,拥有什么功能,如果对其原理认识不到时,也不能达到一比一还原 bind bind执行返回的是一个新的函数 这个函数可以被new关键字执 ...

  3. 关于代码手写UI,xib和StoryBoard

    代码手写UI 这种方法经常被学院派的极客或者依赖多人合作的大型项目大规模使用.Geek们喜欢用代码构建UI,是因为代码是键盘敲出来的,这样可以做到不开IB,手不离开键盘就完成工作,可以专注于编码环境, ...

  4. 【Xamarin挖墙脚系列:代码手写UI,xib和StoryBoard间的博弈,以及Interface Builder的一些小技巧(转)】...

    正愁如何选择构建项目中的视图呢,现在官方推荐画板 Storybord...但是好像 xib貌似更胜一筹.以前的老棒子总喜欢装吊,用代码写....用代码堆一个HTML页面不知道你们尝试过没有.等页面做出 ...

  5. 代码手写UI,xib和StoryBoard间的博弈,以及Interface Builder的一些小技巧

     http://www.cocoachina.com/industry/20140102/7640.html 最近接触了几个刚入门的iOS学习者,他们之中存在一个普遍和困惑和疑问,就是应该如何制作 ...

  6. 代码手写UI,xib和StoryBoard间的博弈

    代码手写UI,xib和StoryBoard间的博弈         火龙果软件 发布于 2014-1-3 最近接触了几个刚入门的iOS学习者,他们之中存在一个普遍和困惑和疑问,就是应该如何制作UI界面 ...

  7. JAVA项目代码手写吗_一个老程序员是如何手写Spring MVC的

    见人爱的Spring已然不仅仅只是一个框架了.如今,Spring已然成为了一个生态.但深入了解Spring的却寥寥无几.这里,我带大家一起来看看,我是如何手写Spring的.我将结合对Spring十多 ...

  8. 【JS】584- 20行代码​手写 async / await​​​​

    晨曦时梦见兮 https://juejin.im/post/5e79e841f265da5726612b6e 前言 如果让你手写 async 函数的实现,你是不是会觉得很复杂?这篇文章带你用 20 行 ...

  9. 一百多行 Python 代码手写蕃茄钟

    对现实不满,充满无力感,可是作为一个码农,大时代里的一个小人物,并不能改变什么,只能在程序代码里的世界里找点乐趣吧, 东坡先生如是说: 莫听穿林打叶声,何妨吟啸且徐行.竹杖芒鞋轻胜马,谁怕?一蓑烟雨任 ...

最新文章

  1. 解决方案 | 阴阳师御用动画制作团队,丁磊的秘密武器
  2. boost::safe_numerics::cpp相关的测试程序
  3. CSS基础---日记4
  4. efcore根据多个条件更新_EF Core 基础知识
  5. 推荐一个女画家的系列画:《公主的妄想症》之《喜欢就是要全部》
  6. python调用simulink_使用Python从dbc文件中提取simulink建模数据定义
  7. CABAC熵编码代码实现(H264)-FFMPEG
  8. Linux学习6之软件包管理--yum在线管理
  9. vue cli3 项目中解决跨域
  10. win7下MongoDB集群告别裸奔
  11. java学习(java入门)
  12. python numpy函数手册_NumPy常用中文手册.pdf
  13. nmap 扫描常见端口——命令
  14. ubuntu 自动登录账户_Ubuntu如何启用root默认自动登录
  15. C语言工程网络图,三分钟教你学会 双代号网络图的绘制
  16. 4.默认参数,不定参数,扩展参数
  17. Python工程师需要学习的知识总结,送给需要的人
  18. 震惊了!原来这才是kafka!
  19. SLIC Superpixels 算法学习笔记
  20. IDA使用手册_(1)

热门文章

  1. 3句话点评2020年看过的那些精彩的电影
  2. 2020年,知识图谱都有哪些研究风向?
  3. 华为高级研究员谢凌曦:下一代人工智能计算模型探索
  4. 顶会「扩招」,一地鸡毛:ICLR2020近半数审稿人未发过相关论文
  5. AI安防崛起迅速 开疆拓土少不了专利作“盔甲”
  6. 自动驾驶车辆何时实现?近期不会实现的五大原因
  7. 深度丨当AI变得无处不在,人类社会将发生这五大变化!
  8. Pytorch+Text-CNN+Word2vec+电影评论情感分析实战
  9. 诺奖10年,干细胞领域再突破!华大单细胞技术助力获得人类体外诱导全能干细胞...
  10. AI芯片:从历史看未来