,大家好,我是前端西瓜哥。,之前写了一篇关于 JS 中 bind 方法的实现的文章,并给出了实现:,但没有处理 通过 new 创建实例 的情况。,因为很少会遇到给 bind 返回的函数做 new 操作的场景,所以我没去考虑这种特殊情况。,但面试中还是会涉及到的,我们还是实现一下兼容 new 操作的 bind 写法,顺便学习一下 new 操作符。,因为存在一定上下文,在阅读本文前,建议先阅读前一篇文章:《前端面试题:手写 bind》。,我们先学习一下 new 操作符。,new 用于通过函数来创建一个对象实例,在很多语言中都能看到。,JS 的函数,除了可以是普通函数,比如:,还可以是构造函数,只需要在构造时在它前面加一个 new:,new 创建一个新对象,做了下面几件事:,怎么判断一个函数正在被 new 操作符调用?,答案是 使用 instanceof 判断 this 是否为当前函数的实例,即 this instanceof Fn 为 true,表示在通过 new 构建实例。,我们看一个例子:,在 Vuejs 的源码,你会看到下面代码,这里也用到了这个技巧。,你在开发环境如果不通过 new 来使用 Vue 对象,会在控制台提示你要通过 new 来调用 Vue。,如果我们 new 的是 Function.prototype.bind 返回的新函数,会发生什么事情?,结果等价于直接去 new 原始函数。,不同的是,仍旧可以进行参数的预置。可以看到,构造函数的第一个参数,在调用 bind 的时候就提前设置为 ‘前端西瓜哥’。,完整实现如下:,这里我通过 this instanceof boundFn 来判断是否用了 new,如果是,就直接 new 原始函数然后返回,记得带上 bind 预置好的参数。,其他保持原样(具体见上文《前端面试题:手写 bind》)。,boundFn.prototype = fn.prototype; 这个可写可不写,只是让 bind 返回的新函数的 prototype 指向原函数的 prototype。,如果是原生 bind 返回的函数,它是没有 protoype 属性的,可以认为它是一种特别的函数,而我们实现的 bind 返回的却是一个普通函数,所以并不能完全模拟的。,如果你 追求完美的实现,可以研读一下 Function.prototype.bind 的标准:,https://tc39.es/ecma262/#sec-function.prototype.bind。,然后再看看知名的 core.js 库中对 bind 的实现:,https://github.com/zloirock/core-js/blob/cafe9ecf2b384385f8b8d1da0047e44586fff2dc/packages/core-js/internals/function-bind.js#L23-L33。,其中核心实现为:,这里有更多的细节:,手写 bind,现在想来并不简单,需要掌握好很多知识点:
© 版权声明
文章版权归作者所有,未经允许请勿转载。