问题
In ES5, Boolean.prototype
is a Boolean object:
The Boolean prototype object is itself a Boolean object (its [[Class]] is "Boolean") whose value is false.
In ES6 / ES2015, it isn't:
The Boolean prototype object is an ordinary object. It is not a Boolean instance and does not have a [[BooleanData]] internal slot.
In ES2016, it is once again:
The Boolean prototype is itself a Boolean object; it has a [[BooleanData]] internal slot with the value false.
(and it remains so in ES2017 as well.)
The same is true for Number.prototype
and String.prototype
—while on the other hand Date.prototype
and RegExp.prototype
also began as instances of their respective [[Class]]es in ES5.1, became plain Objects
in ES6 and have remained that way since.
The reversion, in ES2016, does not appear to have been the subject of any tc39 proposal.
Why were these changes made in ES6, and then (only) partially reverted in ES2016?
(This question is not just for academic/historical interest: I am working on a JavaScript dialect that is intended not to include the boxed primitive types but which still requires the .prototype
objects to hold all the methods that can be invoked on primitive values, and while it's feasible to special-case the .prototype
objects as being the only instances of their respective [[Class]]es, I'd like to understand why that might be desirable.)
回答1:
I have not been able to find an full explanation of why these objects became plain Object
s in ES6, but the reason for the rollback appears to be because it caused unexpected problems: from "Number.prototype not being an instance breaks the web, too" on esdiscuss.org:
V8 just rolled a change into Canary yesterday that implements the new ES6 semantics for Number.prototype (and Boolean.prototype) being ordinary objects. Unfortunately, that seems to break the web. In particular jsfiddle.net/#run fails to load now.
What I see happening on that page is a TypeError "Number.prototype.valueOf is not generic" being thrown in this function (probably part of moo tools):
Number.prototype.$family = function(){ return isFinite(this) ? 'number' : 'null'; }.hide();
after being invoked on Number.prototype.
AFAICS, that leaves only one option: backing out of this spec change.
–Andreas Rossberg
And it seems that the rollback was not applied to Date.prototype
and RegExp.prototype
because they carry mutable state:
From a security pov, the important ones not to revert are those carrying mutable state not locked down by Object.freeze. In ES5 this was only Date.prototype. Of the ES5 builtins in ES6, this now includes RegExp.prototype because of RegExp.prototype.compile.
—Mark S. Miller
来源:https://stackoverflow.com/questions/50614565/why-is-boolean-prototype-a-boolean-object-again-and-same-for-string-and-number