6

我似乎错过了一些关于 Javascript 中的构造函数链继承的东西,以及原生对象。例如 :

function ErrorChild(message) { Error.call(this, message); }
ErrorChild.prototype = Object.create(Error.prototype);
var myerror = new ErrorChild("Help!");

为什么myerror.message定义为""在那些语句之后?我希望错误构造函数将其定义为“帮助!” (并覆盖 的默认值Error.prototype.message),就像我在做的那样:

var myerror = new Error("Help!")

非常感谢 !

4

2 回答 2

4

简单的解决方法:工作小提琴

function ErrorChild(name, message) {
    // Error.call(this); this is not needed
    this.name = name;
    this.message = message;
}

ErrorChild.prototype = Object.create(Error.prototype);
ErrorChild.prototype.constructor = ErrorChild;

var myerror = new ErrorChild("test", "Help!");
document.body.innerHTML += myerror.message;

以上并没有破坏预期的行为。当你throw myerror,正确的namemessage将显示。

问题

来自 ECMA5 语言规范:

15.11.1 作为函数调用的错误构造函数

当 Error 作为函数而不是构造函数调用时,它会创建并初始化一个新的 Error 对象。因此,函数调用 Error(...) 等效于具有相同参数的对象创建表达式 new Error(...)。

问题:Error.call(this), 等价于new Error。但是new Error实例化不会设置nameor message。将默认new Error初始化。message""

15.11.4.3 Error.prototype.message # Ⓣ Ⓡ Error.prototype.message 的初始值为空字符串。

测试证明

如果在您ErrorChild的内部,您要添加:

var test = Error.call(this, message);
console.dir(test);
console.log(test instanceof Error); // true;
console.log(test.message); // "Help!";

test反映了 ECMA5 规范。Error具有适当message集合的实例。

结论:

因为Error.call(arguments);自动转换为new Error(arguments);范围会丢失,所以永远不会在this对象上初始化属性。

使用时Object.create(Error.prototype),该message属性采用默认值,即空字符串。

于 2013-05-13T08:33:43.300 回答
1

问题不是继承链,而是作为函数调用Error的行为就像调用构造函数一样,实例化了一个new Error对象

因此,当调用您new ErrorChild执行的代码实际上相当于

function ErrorChild(message) {
 new Error (message) 
}

等待。但这只会创建一个新的错误对象,它不会在任何地方使用(也不会由您的构造函数返回)。并且只是被遗忘。

所以这实际上并没有修改你的实际ErrorChild实例。

因此,message您正在访问的属性是ErrorChild.prototype继承自的属性Error.protyotype,因此包含message默认值是一个空字符串""

但是你可以简单地“模仿”一个错误对象。

因为您只需要toString方法的定义行为和 2 个属性

  • name
  • message

覆盖错误的标准属性。

您可以简单地将构造函数原型设置为并手动Error.prototype 分配。namemessage

function ErrorChild (name,message) {
  this.name = name;
  this.message = message;
}
ErrorChild.prototype = Error.prototype;

现在您可以简单地创建一个new ErrorChild (...)实例。

你可以throw围绕logcatch->

throw new ErrorChild("CustomError","Help") //Uncaught CustomError: Help

这是一个JSBin 演示

于 2013-05-13T09:28:08.000 回答