Why does Boolean primitive not call prototype toString()?
Asked Answered
A

2

10

Say I have this code:

Boolean.prototype.toString = function toString() {
  return this.valueOf() ? '1' : '0';
};

var object = {
  true: 'true',
  false: 'false',
  1: '1',
  0: '0'
};

// "true" - this doesn't work
console.log('primitive', object[true]);
// "1" - but these do
console.log('primitive.toString()', object[true.toString()]);
console.log('instance', object[new Boolean(true)]);

Why doesn't the primitive use the class's toString definition? Object keys are either strings or symbols, they cannot just be raw booleans. This is why I'm confused.

Afroasian answered 6/6, 2016 at 13:55 Comment(7)
because the primitive has no method toString, its just a value.Jensen
@NinaScholz but I thought that a value had to be coerced to a string when it was used as a key for an object. Also, after redefining Boolean.prototype.toString(), calling true.toString() returns "1". So that sort of disproves your claim that true has no method toString().Afroasian
it's printing primitive true, instance 1. Is that not what you expect?Chalkstone
@Mike no, because object keys are strings, and if you were to run true.toString() after redefining Boolean.prototype.toString(), it returns "1", not "true".Afroasian
@PatrickRoberts ok, got that. thanks :)Chalkstone
object[true.toString()] != object[true]Giselegisella
@VladuIonut yes that is what I'm getting at. But why?Afroasian
A
8

Because the specifications says so. http://www.ecma-international.org/ecma-262/6.0/index.html#sec-tostring In this table the String values of primitives are defined. Only for Objects ToPrimitive is used.


The table tells us thatToString for an Object o is ToString( ToPrimitive(o, "string"))

The Specification tells us that if ToPrimitive is called with an Object we have to follow these steps:

1. If PreferredType was not passed, let hint be "default".
2. Else if PreferredType is hint String, let hint be "string".
3. Else PreferredType is hint Number, let hint be "number".
4. Let exoticToPrim be GetMethod(input, @@toPrimitive).
5. ReturnIfAbrupt(exoticToPrim).
6. If exoticToPrim is not undefined, then
  a. Let result be Call(exoticToPrim, input, «hint»).
  b. ReturnIfAbrupt(result).
  c. If Type(result) is not Object, return result.
  d. Throw a TypeError exception.
7. If hint is "default", let hint be "number".
8. Return OrdinaryToPrimitive(input,hint).

@@toPrimitive beeing set is a special case so we now have to look at OrdinaryToPrimitive

1. Assert: Type(O) is Object
2. Assert: Type(hint) is String and its value is either "string" or "number".
3. If hint is "string", then
  a. Let methodNames be «"toString", "valueOf"».
4. Else,
  a. Let methodNames be «"valueOf", "toString"».
5. For each name in methodNames in List order, do
  a. Let method be Get(O, name).
  b. ReturnIfAbrupt(method).
  c. If IsCallable(method) is true, then
    i. Let result be Call(method, O).
    ii. ReturnIfAbrupt(result).
    iii. If Type(result) is not Object, return result.
6. Throw a TypeError exception.

So this means that the return value of ToPrimitive(o, "string") is o.toString() and toString(o.toString()) is the same as o.toString().

Aphesis answered 6/6, 2016 at 14:6 Comment(3)
Great edit! I think that answers everything, thanks for the thorough answer!Afroasian
@DavidDiez Nobody reads the manual. If you think this is untrue you're just kidding yourself ;)Afroasian
@Patrik, I know hehe. I was just kidding, hence the "quotes" ;)Gawain
G
3
  • "true" is a boolean.
  • A "Boolean" instance is an object, not a boolean.
  • So the instance is not obliged to use the prototype.
  • "Boolean" object is just an abstraction in js for using boolean type.

Boolean.prototype.toString=function toString(){
  return this?'1':'0';
};

var object = {
  'true':'true',
  'false':'false',
  '1':'1',
  '0':'0'
};

console.log('primitive', object[true]);
console.log('instance', object[new Boolean(true)]);
console.log('bool type:', typeof(true));
console.log('Boolean type:', typeof(new Boolean(true)));
Gawain answered 6/6, 2016 at 14:6 Comment(1)
Thanks for the explanation, I think @TillArnold explains more thoroughly why "primitives are not obliged to use the prototype".Afroasian

© 2022 - 2024 — McMap. All rights reserved.