MDN Function.prototype.bind绑定函数称为构造函数 [英] MDN Function.prototype.bind bound function called as constructor

查看:168
本文介绍了MDN Function.prototype.bind绑定函数称为构造函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道当 Function.prototype.bind 返回的函数被调用为构造函数时,预绑定 this 被忽略。这是ECMA-262中指定的行为,以及 MDN polyfill 实现。我的问题是:在这种情况下,polyfill如何工作?我知道这段代码对此有反应:

I know that when a function returned by Function.prototype.bind is called as a constructor, the pre-bound this is ignored. This is the behaviour specified in ECMA-262, and the behaviour that MDN polyfill implements. My question is: how that polyfill works in that case? I know that this code is responsoble for that:

fNOP = function () {}

return fToBind.apply(this instanceof fNOP && oThis
             ? this
             : oThis,

fNOP.prototype = this.prototype;
fBound.prototype = new fNOP();

但为什么他们需要创建这个虚拟函数( fNOP ),实例化它并分配给 fBound 的原型等等。为什么他们只能这样写:

But why do they need to create this dummy function (fNOP), instantiate it and assign to the fBound's prototype and so on. Why can's they just write this:

fBound = function foo() {
      return fToBind.apply(this instanceof foo
             ? this
             : oThis,
             aArgs.concat(Array.prototype.slice.call(arguments)));
    };

推荐答案

Polyfilling bind 很难,如果不是e不可能做到相关的。如果您查看规范,您会注意到绑定函数是Function对象

Polyfilling bind is hard, if not even impossible to do correclty. If you take a look at the spec, you notice that bound functions are Function objects

  • with a custom [[Call]] internal property
  • with a custom [[Construct]] internal property
  • with a custom [[HasInstance]] internal property
  • without a .prototype property
  • with a specific .length property

显然,第一个质量是最重要的,所以我们所做的就是返回一个表现出这种行为的函数。您已经注意到并非一切都可以正常完成,因为 .length 的函数是不可写的,而 prototype (隐式创建)是不可删除的。

Clearly, that first quality is the most important, so what we do is to return a function that exhibits this behaviour. You already notice that not everything can be done properly, as .length of functions is non-writable, and prototype (implicitly created) is non-deleteable.

那么如何实现[[Construct]]?我们需要确定是否使用 new 表达式调用该函数。这不能可靠地完成,因为 新的电话可能会伪造帮助 .call() / .apply() Object.create()。所以通常做的是测试 Object.getPrototypeOf(this)=== constructor.prototype ,或者更简单的只是这个instanceof构造函数。如果需要,我们会伪造带有扩展参数的待绑定函数的[[Construct]]调用。

So how to implement [[Construct]]? We would need to determine whether the function was called with a new expression. This cannot be done reliably, as a new call could be faked with the help of .call()/.apply() and Object.create(). So what is usually done is testing Object.getPrototypeOf(this) === constructor.prototype, or more simple just this instanceof constructor. If required, we then would fake the [[Construct]] call of the to-be-bound function with the extended arguments.

那么如何实现[[HasInstance] ]?操纵它的唯一方法是 .prototype 的值,它用于原型链查找。要使 fBound。[[HasInstance]] 的工作方式与 fToBind相同。[[HasInstance]] ,我们需要设置 fBound.prototype = fToBind.prototype

So how to implement [[HasInstance]]? The only way to manipulate this is the value of the .prototype, which is used for the prototype chain lookups. To make fBound.[[HasInstance]] work the same way as fToBind.[[HasInstance]], we need to set fBound.prototype = fToBind.prototype.

但是,如果我们这样做,那就是[[Construct]当绑定函数的实例调用绑定函数时,]检查将失败。嗯。

However, if we do that, the is[[Construct]]ing check will fail us when the bound function is called on instances of the binded function. Hmm.

因此,我们需要平衡可能解决方案的权衡。可以按照建议的方式更改MDN polyfill,可以更改为传递 Object.create(fToBind.prototype)而不是等。

So, we will need to balance the trade-offs of the possible solutions. The MDN polyfill could be changed in the way you suggest, could be changed to pass Object.create(fToBind.prototype) instead of this, etc.

Property                      | current MDN |  your    | … with same
                              | polyfill    | solution | prototypes
------------------------------+-------------------------------------------
fBound(…) uses boundThis      | yes           yes        yes
                              | 
new fBound(…) ignores it      | yes           yes        yes
                              |
fBound.call(new fToBind)      | yes           yes        no
 uses boundThis               |
                              |
new fToBind instanceof fBound | no            no         yes
                              |
new fBound instanceof fBound  | yes           yes        yes
                              |
new fBound instanceof fToBind | yes           no         yes
                              |
Object.getPrototypeOf(new     | no            no         yes
 fBound)==fToBind.prototype   |

这篇关于MDN Function.prototype.bind绑定函数称为构造函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆