Reputation: 8467
Probably a naive question - if this snippet is executed (I'm running with Node.js v12.16.3
, same result in Chrome apart from the error type):
const obj = {}
Object.defineProperty(obj, 'a', {
writable: false,
value: 13
})
obj.a = 14
It will, obviously, throw an error, but the message string of that error has strange representation of an object:
TypeError: Cannot assign to read only property 'a' of object '#<Object>'
The question is - why it's stringified as #<Object>
?
Defining a toString
method on the object will render it as if it were called with 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]'
While console.log
outputs correctly. How to make that TypeError
output the correct string representation? What does it use internally?
Upvotes: 2
Views: 308
Reputation: 276266
Node.js and Chrome share the same JavaScript engine called V8. That engine hard-codes the string "#" in the error message.
It uses the template:
T(StrictReadOnlyProperty, \
"Cannot assign to read only property '%' of % '%'")
Which in turn gets interpolated as the object's constructor name. In this case Object
. You can see this:
const obj = {};
obj.constructor.name; // Object
const obj2 = new class Bar {};
obj2.constructor.name; // Bar
Or, in your example:
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
Note the spec just says: "throw a TypeError exception." - this behaviour is entirely defined by the V8 engine and not JavaScript.
Upvotes: 1