重现问题
在尝试使用web套接字传递错误消息时,我遇到了一个问题。我可以使用JSON.stringify
复制我面临的问题,以迎合更广泛的受众:
// node v0.10.15
> var error = new Error('simple error message');
undefined
> error
[Error: simple error message]
> Object.getOwnPropertyNames(error);
[ 'stack', 'arguments', 'type', 'message' ]
> JSON.stringify(error);
'{}'
问题是我最终得到了一个空的对象。
我尝试过的
浏览器
我首先尝试离开node.js并在不同的浏览器中运行它。Chrome版本28给了我同样的结果,有趣的是,Firefox至少做了一次尝试,但省略了这条消息:
>>> JSON.stringify(error); // Firebug, Firefox 23
{"fileName":"debug eval code","lineNumber":1,"stack":"@debug eval code:1\n"}
替换函数
然后我看了看Error.prototype。它表明原型包含诸如toString和toSource之类的方法。知道函数不能被字符串化,我在调用JSON.stringify来删除所有函数时包含了一个replacer function,但后来意识到它也有一些奇怪的行为:
var error = new Error('simple error message');
JSON.stringify(error, function(key, value) {
console.log(key === ''); // true (?)
console.log(value === error); // true (?)
});
它似乎不会像往常一样循环遍历对象,因此我不能检查键是否是函数并忽略它。
问题是
有没有办法用JSON.stringify
把本机错误消息串起来?如果不是,为什么会发生这种行为?
绕过这个问题的方法
更新
@Ray Toal在评论中建议我看看property descriptors。现在很清楚为什么它不起作用了:
var error = new Error('simple error message');
var propertyNames = Object.getOwnPropertyNames(error);
var descriptor;
for (var property, i = 0, len = propertyNames.length; i < len; ++i) {
property = propertyNames[i];
descriptor = Object.getOwnPropertyDescriptor(error, property);
console.log(property, descriptor);
}
输出:
stack { get: [Function],
set: [Function],
enumerable: false,
configurable: true }
arguments { value: undefined,
writable: true,
enumerable: false,
configurable: true }
type { value: undefined,
writable: true,
enumerable: false,
configurable: true }
message { value: 'simple error message',
writable: true,
enumerable: false,
configurable: true }
密钥:enumerable: false
。
Accepted提供了解决此问题的方法。
发布于 2013-08-23 05:48:09
您可以定义Error.prototype.toJSON
来检索表示Error
的普通Object
if (!('toJSON' in Error.prototype))
Object.defineProperty(Error.prototype, 'toJSON', {
value: function () {
var alt = {};
Object.getOwnPropertyNames(this).forEach(function (key) {
alt[key] = this[key];
}, this);
return alt;
},
configurable: true,
writable: true
});
var error = new Error('testing');
error.detail = 'foo bar';
console.log(JSON.stringify(error));
// {"message":"testing","detail":"foo bar"}
使用Object.defineProperty()
添加toJSON
,但它本身不是enumerable
属性。
关于修改Error.prototype
,虽然可能没有专门为Error
定义toJSON()
,但通常为对象定义the method is still standardized (参见:步骤3)。因此,冲突或冲突的风险是最小的。
不过,为了完全避免这种情况,可以使用JSON.stringify()
's replacer
parameter:
function replaceErrors(key, value) {
if (value instanceof Error) {
var error = {};
Object.getOwnPropertyNames(value).forEach(function (propName) {
error[propName] = value[propName];
});
return error;
}
return value;
}
var error = new Error('testing');
error.detail = 'foo bar';
console.log(JSON.stringify(error, replaceErrors));
发布于 2014-10-05 12:57:05
JSON.stringify(err, Object.getOwnPropertyNames(err))
似乎很管用
[from a comment by /u/ub3rgeek on /r/javascript]和felixfbecker的评论如下
发布于 2018-06-07 17:50:33
由于没有人谈论为什么部分,我将回答它。
为什么此 JSON.stringify
返回空对象?
> JSON.stringify(error);
'{}'
应答
从JSON.stringify()的文档中,
对于所有其他对象实例(包括Map、Set、WeakMap和WeakSet),只有它们的可枚举属性将被序列化。
而且Error
对象没有它的可枚举属性,这就是为什么它打印一个空对象。
https://stackoverflow.com/questions/18391212
复制相似问题