首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >ecmascript-6 Function.prototype.bind()如何处理类构造函数?

ecmascript-6 Function.prototype.bind()如何处理类构造函数?
EN

Stack Overflow用户
提问于 2021-07-28 02:51:39
回答 1查看 109关注 0票数 0

我完全错过了ES6革命,7年后我又回到了JavaScript,发现许多非常奇怪的事情正在发生。

特别是Function.prototype.bind()处理类构造函数的方式。

考虑到这一点:

代码语言:javascript
复制
// an ES6 class
class class1 {
  constructor (p) {
    this.property = p;
  }
}

var class2 = class1.bind(passer_by);
var class3 = class2.bind(passer_by,3);

class2() // exception, calling a constructor like a function
class3() // idem

console.log (new class1(1)) // class1 {property: 1}
console.log (new class2(2)) // class1 {property: 2}
console.log (new class3() ) // class1 {property: 3}

// An ES5-style pseudo-class
function pseudoclass1 (p) {
  this.property = p;
}

var property = 0;
var passer_by = { huh:"???" }

var pseudoclass2 = pseudoclass1.bind(passer_by);
var pseudoclass3 = pseudoclass1.bind(passer_by,3);

pseudoclass1(1); console.log (property)  // 1 (this references window)
pseudoclass2(2); console.log (passer_by) // Object { huh: "???", property: 2 }
pseudoclass3() ; console.log (passer_by) // Object { huh: "???", property: 3 }

console.log (new pseudoclass1(1)) // pseudoclass1 {property: 1}
console.log (new pseudoclass2(2)) // pseudoclass1 {property: 2}
console.log (new pseudoclass3() ) // pseudoclass1 {property: 3}

显然,class2class3被标识为构造函数,class3class1的一个部分应用程序,它可以生成具有第一个参数的固定值的实例。

另一方面,虽然ES5类型的函数仍然可以充当(可怜人的)构造函数,但它确实可以服务于bind()设置的bind()值,就像它们在不幸的passer_by上运行而不是像无界pseudoclass1那样破坏全局变量时所看到的那样。

显然,所有这些构造函数都以某种方式访问了允许它们构造对象的this值。然而他们的this被认为是绑定到另一个物体上的。

因此,我想一定有某种机制可以将适当的this提供给构造函数,而不是传递给bind()的任何参数。

现在我的问题是,我可以到处找到一些关于它的知识,甚至一些代码显然是来自Chrome的V8版本(函数bind()本身似乎对构造函数做了一些特殊的事情),或者讨论了在原型链中插入的一个神秘的FNop函数,还有,如果我可以说的话,偶尔会有一段货物崇拜的蜂鸣声。

但我找不到的是对这里实际发生的事情的解释,这是为什么实现这样一种机制的理由(我的意思是,使用新的扩展操作符和析构等等,难道不可能产生相同的结果(向构造函数应用一些参数),而不需要对bind()进行适当的文档攻击吗?)及其范围(它对构造函数有效,但是否还有其他类型的函数被传递给bind()?)?

我试着阅读2015年和2022年ECMA 262的规范,但当我的大脑开始从我的耳朵里漏出来时,我不得不停止阅读。我将调用堆栈追溯到:

19.2.3.2

9.4.1.3

9.4.1.2

7.3.13关于构造函数的一些内容是:“如果newTarget未被传递,则此操作等效于: new (...argumentsList)”。啊哈。所以这个伪递归调用应该允许在某种程度上模拟new .Erf..。

如果某个善良而精明的灵魂能让我更好地了解正在发生的事情,向我展示ECMA规范的哪一部分来处理这一机制,或者更普遍地指出我的正确方向,我将不胜感激。

我受够了把头撞在墙上,说实话。这个一点Chrome代码似乎表明bind()正在为构造函数做一些特殊的事情,这对我来说是难以理解的。所以,如果其他一切都失败了,我至少想要一个解释。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-07-28 08:47:36

具体而言,这与类无关,而是与.bind的工作方式有关。

你一直走在正确的轨道上。这里最相关的部分是9.4.1.2

作为一个概述: ECMAScript区分了两种类型的函数:可调用函数和可构造函数。函数表达式/声明都是,而例如,class构造函数只能是可构造的,而箭头函数只能被调用。

在规范中,这是由函数的内部[[Call]][[Construct]]方法表示的。

new将触发内部[[Construct]]方法的调用。

.bind将返回一个具有不同实现的[[Call]][[Construct]]的新函数对象。那么,[[Construct]]是什么样的呢?

9.4.1.2 [构造] 当使用bind函数创建的绑定函数外来对象(F)的[Construct]内部方法使用参数argumentsList和newTarget列表调用时,将执行以下步骤:

  1. 目标为F.[BoundTargetFunction]。
  2. 断言:IsConstructor(目标)为真。
  3. 让boundArgs是F.[BoundArguments]。
  4. 让args是一个包含与列表boundArgs相同顺序的值的新列表,然后是与列表argumentsList相同顺序的值。
  5. 如果SameValue(F,newTarget)为真,则将newTarget设置为目标值。
  6. 回来?构造(目标、args、newTarget)。

这意味着绑定构造函数将使用绑定参数(F.[[BoundTargetFunction]])和传入参数(argumentsList)“构造”原始函数( this ),但它完全忽略了绑定this值(即F.[[BoundThis]])。

但是,除了传递给bind()的值之外,还有其他类型的函数正在被喂入吗?

是的,箭头起作用。箭头函数没有自己的this绑定(而是使用来自最近的this提供环境的值),因此绑定箭头函数也忽略绑定的this值。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68553794

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档