`ToNumber` and `ToString` invoking `toString`/`valueOf` for number/string objects? (Was: Re: Re: Implementing an identical JSON.stringify)
# Jordan Harband (6 years ago)
My assumption is legacy behavior - ie, that's what browsers did, so it had to be codified in the spec.
My assumption is legacy behavior - ie, that's what browsers did, so it had to be codified in the spec. On Sat, Aug 4, 2018 at 10:20 PM, Isiah Meadows <isiahmeadows at gmail.com> wrote: > This makes me wonder: for objects with [[NumberData]] and > [[StringData]], why do they call `valueOf`/`toString`/@@toPrimitive to > coerce them instead of simply accessing the boxed data directly? It > seems like a pointless waste to check. > > ----- > > Isiah Meadows > contact at isiahmeadows.com > www.isiahmeadows.com > > > On Sun, Aug 5, 2018 at 12:30 AM, Michael Theriot > <michael.lee.theriot at gmail.com> wrote: > >> Regarding cases like Reflect.construct(Number, [], String), the reason > >> this throws is because the ToNumber algorithm calls ToPrimitive if its > >> operand is an object. This in turn will call String.prototype.valueOf > on the > >> object which does not have [[StringData]]. There’s nothing funny going > on, > >> it’s just a weird effect in aggregate. You would just need to implement > all > >> the steps here — internal ops like ToNumber, ToPrimitive, etc. It’s not > that > >> it "considers type", but rather that these algorithms will call methods > by > >> specific names on objects they receive. String.prototype and > >> Object.prototype both implement "valueOf", but only the former will > fail the > >> slot check. > > > > > > Thanks for demystifying this. I never realized it was just ducktyping > > .valueOf on the object. > > > > ```js > > Number.prototype.valueOf = () => 0; > > > > JSON.stringify(1); // 1 > > JSON.stringify(new Number(1)); // 0 > > ``` > > > > I guess what confused me is that it would detect a [[NumberData]] > internal > > slot, but instead of unboxing to that value it tries to ducktype call > > .valueOf on the object. So the presence of [[NumberData]] changes the > > behavior even if it does not actually use this value. > > > > On Sat, Aug 4, 2018 at 10:14 PM Darien Valentine <valentinium at gmail.com> > > wrote: > >> > >> Is this a question about how/if one could replicate its behavior in > theory > >> from ES code, or are you suggesting a change to the existing behavior > for > >> these exotic cases? > >> > >> Assuming the former: > >> > >> The relevant steps are > >> [here](https://tc39.github.io/ecma262/#sec-serializejsonproperty). The > >> `instanceof` a value isn’t significant in this algorithm, just its > slots (if > >> it is an object) or its primitive type. So one can handle number and > string > >> by leveraging branded checks as you’ve shown — nothing more is needed > than > >> branded methods and typeof to manage that one. > >> > >> However it is ultimately not possible to replicate because there is no > >> possible brand test for [[BooleanData]]. > >> _______________________________________________ > >> es-discuss mailing list > >> es-discuss at mozilla.org > >> https://mail.mozilla.org/listinfo/es-discuss > > > > > > _______________________________________________ > > es-discuss mailing list > > es-discuss at mozilla.org > > https://mail.mozilla.org/listinfo/es-discuss > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20180804/c9e6a36c/attachment.html>
This makes me wonder: for objects with [[NumberData]] and [[StringData]], why do they call
valueOf
/toString
/@@toPrimitive to coerce them instead of simply accessing the boxed data directly? It seems like a pointless waste to check.Isiah Meadows contact at isiahmeadows.com, www.isiahmeadows.com