在我们的应用程序的NodeJS,我们通过默认的Error对象扩展定义自定义错误类:Object.defineProperty覆盖只读属性
"use strict";
const util = require("util");
function CustomError(message) {
Error.call(this);
Error.captureStackTrace(this, CustomError);
this.message = message;
}
util.inherits(CustomError, Error);
这使我们与堆栈跟踪throw CustomError("Something");
显示正确了, instanceof Error
和instanceof CustomError
都正常工作。
然而,对于我们的API在返回错误(通过HTTP),我们希望将错误转换成JSON。调用JSON.stringify()
上的错误导致"{}"
,这显然不是真正的消费者描述。
为了解决这个问题,我想重写CustomError.prototype.toJSON()
,返回一个对象常量错误的姓名和消息。然后JSON.stringify()
只想字符串化该对象和所有将工作伟大:
// after util.inherits call
CustomError.prototype.toJSON =() => ({
name : "CustomError",
message : this.message
});
不过,我很快发现,这将引发TypeError: Cannot assign to read only property 'toJSON' of Error
。当我试图写入原型时,这可能是有意义的。所以我改变了构造来代替:
function CustomError(message) {
Error.call(this);
Error.captureStackTrace(this, CustomError);
this.message = message;
this.toJSON =() => ({
name : "CustomError",
message : this.message
});
}
这样(我的预期),则CustomError.toJSON功能将被使用,并且CustomError.prototype.toJSON(从错误)将被忽略。
不幸的是,这只是抛出在对象的构造错误:Cannot assign to read only property 'toJSON' of CustomError
。
下一个我试图从文件,其中排序在正在抛出了没有错误的问题解决了去除"use strict";
,虽然toJSON()
功能不使用JSON.stringify()
可言。
在这一点上,我只是绝望,只是尝试随机的东西。最后,我结束了使用Object.defineProperty()
,而不是直接分配给this.toJSON
:
function CustomError(message) {
Error.call(this);
Error.captureStackTrace(this, CustomError);
this.message = message;
Object.defineProperty(this, "toJSON", {
value:() => ({
name : "CustomError",
message : this.message
})
});
这完美的作品。在严格模式下,没有错误被调用,JSON.stringify()
返回{"name:" CustomError", "message": "Something"}
就像我想要的那样。
所以,虽然它的工作原理,因为我希望它到现在为止,我还是想知道:
- 为什么这项工作到底是什么?我期望它是相当于
this.toJSON = ...
,但显然它不是。 - 它应该这样工作吗?即依靠这种行为是否安全?
- 如果不是,我应该如何正确覆盖toJSON方法? (如果可能的话)
看看[我的答案在这里](http://stackoverflow.com/questions/22960493/i-dont-understand-writable-and-configurable-property-attributes-of-objects/22960738#22960738)和看看这是你问的问题。谢谢! –
@ Qantas94Heavy这的确很奇怪,但至少可以解释为什么我无法正常分配给属性。我仍然没有从你的评论中的[链接文章](https://esdiscuss.org/topic/set-and-inherited-readonly-data-properties)中获得:Object.defineProperty是否工作(即覆盖无论如何,只读原型属性)通过设计还是我不应该依赖的这种意外行为? – Lapixx