【问题标题】:How do JavaScript runtimes implement binding functions to objects? [duplicate]JavaScript 运行时如何实现对象的绑定函数? [复制]
【发布时间】:2023-01-26 16:40:44
【问题描述】:

我正在实现一个 JavaScript 解释器,但我无法弄清楚将函数绑定到 JavaScript 中的对象的细节。

一个基本的例子:

const o = {
  x: 1,
  getX: function() {
    return this.x;
  }
};
o.getX(); // returns 1

棘手的部分是当您将 getX 分配给变量时会发生什么:

let gX = o.getX;
gX(); // returns undefined

我的问题是:运行时如何知道 o.getX() 绑定到 o,但 gX() 应该解除绑定?我假设 gXo.getX 指向完全相同的函数!

我首先想到可能 . 的存在是造成差异的原因。因此,在语法中,有一个类似于 <method-call> ::= <expr> '.' ID '(' <expr>* ')' 的产生式,这个表达式的处理方式与“常规”调用(没有.)。

但是下面的表达式似乎反驳了这个理论,因为(o.getX)()也返回了1。然而,以某种神奇的方式,(gX = o.getX)() 返回undefined,尽管我很清楚赋值表达式返回其右侧的大小,所以在这种情况下为o.getX

是否有关于如何实现这些语义的简单解释?我想不出我的运行时应该区分 o.getX 绑定到 o 的方法,但是 gX,即使它指向 o.getX,也没有绑定。

【问题讨论】:

  • 当谈论用function关键字定义的函数时,一个简单的规则是,this总是绑定时函数是称为,无一例外(有时它有点隐藏在实际调用函数的地方)。有关详细信息,请参阅the standard

标签: javascript javascript-objects programming-languages interpreter instance-methods


【解决方案1】:

我的问题是:运行时如何知道o.getX() 绑定到o,但gX() 应该解除绑定? ...我首先想到的是. 的存在可能是造成差异的原因。

不是 . 本身(它也适用于括号表示法),但是,是的,函数调用发生在属性访问操作的直接结果上这一事实告诉 JavaScript 引擎使用什么值作为 @987654331 @ 调用函数时。

如果我们从property accessors开始,你可以看到结果(通过EvaluatePropertyAccessWithIdentifierKeyMemberExpression .标识符名称(例如)是一个Reference Record,其中包含由成员表达式作为其 [[Base]] 值。该参考记录在执行 function call 时使用,最终在 EvaluateCall 中使用,在那里它获得这个值从参考记录的 [[Base]] 使用。

只是做gX()时,没有属性表达式,并且参考与 EvaluateCall 一起使用的不是参考记录,因此这个值使用的是undefined。 ([[Call]] 函数的内部方法可能会将 undefined 转换为 globalThis,如果它是松散模式函数;当然,箭头函数会忽略调用它们时使用的 this — 但这些是不同的主题。 )

【讨论】:

    猜你喜欢
    • 2011-11-20
    • 1970-01-01
    • 2017-05-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-26
    • 2014-04-11
    • 2013-12-18
    相关资源
    最近更新 更多