2

对于此代码,我在 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 使用与预期不同的 this 对象调用消息 getter 引起的。

火狐/Safari 输出:"Error: fancy:hi"

铬输出:"Error: fancy:undefined"

知道这里发生了什么吗?

测试版本

铬:30.0.1599.69 OSX

火狐:24 OSX

Safari:6.0.5 OSX

4

1 回答 1

2

这绝对似乎是 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

第一种情况发生的事情很容易理解:

  1. fe.message使用参数提示调用[[Get]]onfe"message"
  2. [[Get]]第 1 步获取在fe的原型上设置的访问器描述符(因为fe没有它自己的message属性)。
  3. [[Get]]第 6 步调用访问器描述符上的 getter,并将thisset 设置为调用的原始对象[[Get]](此处为fe对象)。

第二种情况很奇怪。似乎对的原型中的实例fe.toString()执行了[[Get]]for 。这似乎是错误的,因为步骤 5指定从函数中的值获取。"message"ErrorfeError.prototype.toStringmessagethistoString

编辑

我之前认为这个问题是由feError的原型链引起的。但是,考虑这种情况:

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.messagefancy:I'm the instance如上_
  • Error.prototype.toString.call(fe)Error: fancy:I'm the prototype

因此,我们必须得出结论,ChromeError.prototype.toString错误地使用了包含 getter 的原型作为 的thisgetter,这似乎与 的正常行为[[Get]]和/或第 5 步相矛盾Error.prototype.toString

于 2013-10-10T19:34:59.930 回答