从Javascript构造函数调用成员函数

naz*_*bot 10 javascript

我遇到了以下问题,这让我很难过:

我有

function SystemList(UID)
{
  this.refreshData();
}

SystemList.prototype.refreshData = function()
{
  this.systemDataObj({}, $.proxy(this.readSuccess, this));
}
Run Code Online (Sandbox Code Playgroud)

当我尝试运行它时,我收到以下错误:Uncaught TypeError:Object#在构造函数中没有方法'refreshData'.

任何人都知道为什么会失败?在我看来它看起来应该是有效的.

编辑:

我如何创建实例的示例:

function UserMiniProfile(UID)
{
  this.UID = UID;
  this.systemList = new SystemList(this.UID);
  this.htmlID = 'user-'+this.UID+'-profile';
}
Run Code Online (Sandbox Code Playgroud)

T.J*_*der 14

我想你可能会遇到如何以及何时发生函数声明与逐步代码(规范调用语句代码)的问题.

像这样的代码将以您描述的方式失败,例如:

var obj = new Thingy("Fred");

function Thingy(name) {
    this.setName(name);
}

Thingy.prototype.setName = function(name) {
    this.name = name;
};
Run Code Online (Sandbox Code Playgroud)

...因为在将setName函数添加到原型之前,您正在调用构造函数.请注意,在声明之前调用构造函数就好了,这只是因为构造函数正在使用稍后由语句代码设置的函数,即存在问题.JavaScript解释器尝试处理该代码的顺序是:

  1. 创建函数Thingy并使其可用于范围.
  2. 执行该var obj = ....行,调用构造函数.
  3. 执行构造函数的代码(在这种情况下抛出异常,因为没有this.setName函数).
  4. 执行该Thingy.prototype.setName = ...行.(如果在最后一步没有抛出任何异常,那就是.)

这些步骤发生在每个脚本块中(首先完成函数声明,然后按顺序执行语句代码),即使上面的例子非常明显,当你开始将各个不同位置的片段放在一起时,你可以创建这个情况不太明显.

显然,解决方案是确保在设置setName属性之前不构造对象:

function Thingy(name) {
    this.setName(name);
}

Thingy.prototype.setName = function(name) {
    this.name = name;
};

var obj = new Thingy("Fred");
Run Code Online (Sandbox Code Playgroud)

......而且,上述情况相当明显,但在现实世界中创造这些情况的可能性相对较小.

我怀疑这就是你的情况.很容易证明:在Firefox,VS.Net或IE的脚本调试器,Chrome的DevTools等上使用类似Firebug的调试器,在线路上设置断点并SystemList.prototype.refreshData = ...在线路上设置断点,new SystemList(...)并查看哪个一个先执行.

这里有一些小问题证明了这个问题:这个问题在构造函数中失败了,这个问题成功了.