JavaScript:构造函数声明在函数中相对于使用的位置

JavaScript:构造函数声明在函数中相对于使用的位置,javascript,constructor,declaration,evaluation,Javascript,Constructor,Declaration,Evaluation,类似的答案表明,当读取JavaScript文件时,函数声明在第一次传递期间加载到内存中,表达式在随后的传递中求值。但是,下面的示例显示,函数中的函数是在执行代码后编译的 要使下面的代码正常工作,我必须将子构造函数移到test函数之外,或者如果它要留在test函数中,则将其放在调用新子()之前。在其当前位置,您将得到一个TypeError:当您运行代码时,this.init不是一个方法 在哪里可以找到有关何时对函数中的函数声明求值的详细信息 document.addEventListener('D

类似的答案表明,当读取JavaScript文件时,函数声明在第一次传递期间加载到内存中,表达式在随后的传递中求值。但是,下面的示例显示,函数中的函数是在执行代码后编译的

要使下面的代码正常工作,我必须将
子构造函数
移到test函数之外,或者如果它要留在
test
函数中,则将其放在调用
新子()之前。在其当前位置,您将得到一个
TypeError:当您运行代码时,this.init不是一个方法

在哪里可以找到有关何时对函数中的函数声明求值的详细信息

document.addEventListener('DOMContentLoaded', function() {
  test()
}, false)


function test() {
  // Child declaration can go here

  var child = new Child()

  // If Child is placed here, this.init is undefined
  function Child() {
    this.init()
  }
  Child.prototype = new Ancestor(Child)
}


function Ancestor(constructor) {
  this.constructor = constructor
}
Ancestor.prototype.init = function init() {
  console.log(this)
}

// Child declaration can go here
问题是init方法来自祖先类。在创建子实例后,您将继承它。例如,下面的代码可以工作

setTimeout(function() {
    test()
}, 200);

function test() {
  // Child declaration can go here

  Child.prototype = new Ancestor(Child);
  var child = new Child();  

  // If Child is placed here, this.init is undefined
  function Child() {
    this.init()
  }

}

function Ancestor(constructor) {
  this.constructor = constructor
}
Ancestor.prototype.init = function init() {
  console.log(this)
}
因此,只需将Child.prototype=新祖先(Child)移动到新子级调用上方即可。您不需要将子构造函数放在测试函数之外


换句话说,在您的示例中,当您调用新的Child时,init方法仍然没有附加到Child原型。

您的答案非常合理。我一直假设所有
Function.prototype.method=…
调用都是在编译函数本身的同时进行计算的,但现在我知道它们是在第二次过程中进行计算的。您对代码行的重新排序清楚地表明了这一点。但是,如果函数声明和它的原型方法都放在一起,那么代码的可读性会更好,而不是调用
newchild()
。是的,我同意你的看法。