JavaScript TypeError,将对象打印为“#<Object>”字符串

JavaScript TypeError, prints object as '#<Object>' string

可能是一个天真的问题 - 如果执行此代码段(我是 运行 Node.js v12.16.3,除了错误类型外,Chrome 中的结果相同):

const obj = {}

Object.defineProperty(obj, 'a', {
  writable: false,
  value: 13
})

obj.a = 14

显然,它会抛出一个错误,但该错误的消息字符串具有奇怪的对象表示形式:

TypeError: Cannot assign to read only property 'a' of object '#<Object>'

问题是 - 为什么它被字符串化为 #<Object>

在对象上定义一个 toString 方法将呈现它就像用 Object.prototype.toString.call(obj):

调用一样

const obj = {
  toString () {
    return 'stringified obj'
  }
}

Object.defineProperty(obj, 'a', {
  writable: false,
  value: 13
})

console.log(`${obj}`)

obj.a = 14

TypeError: Cannot assign to read only property 'a' of object '[object Object]'

console.log 输出正确。如何使 TypeError 输出正确的字符串表示形式?它在内部使用什么?

Node.js 和 Chrome 共享同一个 JavaScript 引擎 V8。该引擎在错误消息中对字符串“#”进行了硬编码。

它使用the template:

T(StrictReadOnlyProperty,                                                    \
    "Cannot assign to read only property '%' of % '%'") 

这又被插值为 object's constructor name。在这种情况下 Object。你可以看到这个:

const obj = {};
obj.constructor.name; // Object

const obj2 = new class Bar {};
obj2.constructor.name; // Bar

或者,在您的示例中:

const obj = new class SomeValue {}

Object.defineProperty(obj, 'a', {
  writable: false,
  value: 13
})

// TypeError: Cannot assign to read only property 'a' of object '#<SomeValue>'
obj.a = 14

注意规范只是说:“抛出 TypeError 异常。” - 此行为完全由 V8 引擎定义,而不是 JavaScript.