对于此代码,我在Chrome与Firefox和Safari中看到了不同的行为:
var FancyError = function(x) { this.x = x; };
FancyError.prototype = new Error;
Object.defineProperties(FancyError.prototype, {
'message': {
'get': function(){ return "fancy:" + this.x; }
}
});
new FancyError("hi") + '';
在严格模式下不会产生任何错误。该错误是由于Chrome使用与预期对象不同的此对象调用消息获取程序而导致的。
Firefox / Safari输出:
"Error: fancy:hi"
Chrome输出:
"Error: fancy:undefined"
知道这里发生了什么吗?
经过测试的版本
铬:30.0.1599.69 OSX
Firefox:24 OSX
Safari:6.0.5 OSX
最佳答案
这肯定是Chrome Error.prototype.toString
中的错误:
var FancyError = function(x) { this.x = x; };
FancyError.prototype = new Error;
FancyError.prototype.x = "I'm the prototype";
Object.defineProperties(FancyError.prototype, {
'message': {
'get': function(){ return "fancy:" + this.x; }
}
});
var fe = new FancyError("I'm the instance");
通过Chrome中的此设置:
fe.message
产生fancy:I'm the instance
fe.toString()
产生Error: fancy:I'm the prototype
第一种情况很容易理解:
fe.message
使用参数[[Get]]
提示在fe
上调用"message"
[[Get]]
步骤1获取在fe
原型上设置的访问器描述符(因为fe
没有它自己的message
属性)。[[Get]]
步骤6调用访问器描述符上的getter,将this
设置为调用[[Get]]
的原始对象(此处为fe
对象)。第二种情况很奇怪。看来
fe.toString()
在[[Get]]
原型中的"message"
实例上为Error
执行fe
。这似乎是错误的,因为Error.prototype.toString
的第5步指定从message
函数中的this
值获取toString
。编辑
我以前曾认为问题是由
fe
的原型链中包含Error
引起的。但是,请考虑这种情况:var FancyError = function(x) { this.x = x; };
FancyError.prototype.x = "I'm the prototype";
Object.defineProperties(FancyError.prototype, {
'message': {
'get': function(){ return "fancy:" + this.x; }
}
});
fe = new FancyError("I'm the instance");
在这种情况下:
fe.message
是上述的fancy:I'm the instance
Error.prototype.toString.call(fe)
是Error: fancy:I'm the prototype
因此,我们必须得出结论,Chrome的
Error.prototype.toString
错误地使用了包含吸气剂的原型作为this
的getter
值,这似乎与[[Get]]
和/或Error.prototype.toString
的第5步的正常行为相矛盾。 。