Javascript 原型链与作用域链

Javascript prototype chain vs scope chain

我创建了一个 javascript 代码片段,这里是 link 到 visualiser

function Foo(name) {
  this.name = name
  this.speak = function() {
    console.log(this.name)
  }
}

function init() {
  function init_() {
    var foo = new Foo('foo')
    foo.hear = function() {
      console.log('i can hear')
    }
    var bar = new Foo('bar')
    bar.look = function() {
      console.log('i can look')
    }
    foo.speak()
    bar.speak()
  }
  
  init_()
}

init()

我有几个问题:

  1. 原型对象又名 Foo.prototype 在哪个阶段创建?当解释器将 Foo 加载到全局范围或首次调用 new Foo() 时,或在任何其他阶段?它的引用存储在哪个词法范围内? (因为可视化器中没有这样的参考)

  2. foobar 是否应该共享属于 Foo.prototype 的方法 speak() 而不是像可视化器中显示的那样拥有自己的副本?

  3. 原型链和作用域链不相关吗?例如,当调用foo.speak()时,首先我们跟踪作用域链得到foo的值,然后跟踪原型链得到speak()?

In which stage is prototype object aka Foo.prototype created? When the interpreter loads Foo to global scope?

是的,原型对象是在创建Foo函数时创建的。

In which lexical scope is its reference stored? (since there's no such ref in visualiser)

在 none 中。它仅存储在 Foo 的 属性 中。

Should foo and bar share the method speak() which belongs to Foo.prototype rather than owning their own copies as shown in visualiser?

是的。该可视化工具似乎是为 Python 构建的,根本不支持原型链接。

Are prototype chain and scope chain unrelated? For example, when foo.speak() is called, first we trace scope chain to get value of foo, then prototype chain to get speak()?

是的,是的。

但是请注意,您找到的可视化工具不显示范围链,它只显示调用堆栈,并且在正确可视化词法范围和闭包方面做得很差。