Object.is()
I wonder why isn't it ====
. Would be funny.
+0
and -0
should be distinguished there. If you don't want them to be, you can always use comparison operators.
We talked about this at the last last TC39 meeting. I joked about adding Object.isz, or (in honor of @izs) Object.izs.
;-)
But we didn't add anything. You can write it yourself, of course (just modify the Object.is polyfill).
My question … is: Wouldn’t Object.is()
be more useful if it didn’t distinguish +0 and -0?
If anecdotal sharing is valuable...
As a JS web developer, I'd say so. I use isNaN weekly, and have never once had to distinguish +/-0. It may be useful in some very limited cases, but for me Object.is would be much more valuable without it. Having the distinction means that in most cases I won't be able to use Object.is because I want +0 to equal -0.
If the thought is that distinguishing +0 and -0 is never useful, then the goal should be to stop distinguishing between them wherever possible.
Currently there are three "strict-ish" equality tests: Strict Equality Comparison (===
), SameValueZero, and SameValue (Object.is
). We'll leave Abstract Equality Comparison (==
) out of this.
- Strict Equality Comparison is used in
case
matching,Array.prototype.indexOf
,Array.prototype.lastIndexOf
, and===
. - SameValueZero is used for
Map
s andSet
s, plus something aboutArrayBuffer
lengths. - SameValue is used in many places throughout the spec, especially relating to property values; it is also used for
WeakMap
s andWeakSet
s.
Note that most of the uses of SameValue are cases where the input is already guaranteed to be either an object (e.g. prototypes, property descriptor set
functions) or a string (property keys). So many of them could be replaced with SameValueZero, or even Strict Equality Comparison, without consequence.
But there are a few cases, e.g. property redefinition, that do distinguish. For example, if you have a non-writable/non-configurable property whose value is -0, then trying to set/redefine that property will fail, since SameValue is used in that test.
If the belief is truly that SameValueZero is more useful than SameValue, perhaps we should consider relaxing that restriction, and allowing people to flip the sign of non-writable zero-valued properties? Indeed, perhaps it would be worth trying to move some of the strict equality comparisons over to SameValueZero, if that doesn't break too many things. I know moving to SameValue has been discussed and rejected in the past, but that was before SameValueZero was baked into the spec.
(I personally dislike the existence of SameValueZero, and would rather stick with SameValue. But I have no reasonable arguments from practicality, only theoretical purity, and so I don't anticipate convincing anyone.)
Domenic Denicola wrote:
If the belief is truly that SameValueZero is more useful than SameValue, perhaps we should consider relaxing that restriction, and allowing people to flip the sign of non-writable zero-valued properties?
You are reasoning from general to particular, but without any reason to focus on the particular of redefining a non-writable property from -0 to +0 or vice versa. There is no use-case "there" there! I bet Mark would find that a subtle security problem.
Indeed, perhaps it would be worth trying to move some of the strict equality comparisons over to SameValueZero, if that doesn't break too many things.
Who knows? 1JS and browser game theory combine to mean no one will risk trying, only to lose compatibility around the edges.
I know moving to SameValue has been discussed and rejected in the past, but that was before SameValueZero was baked into the spec.
No one is discussing changing === and !==, AFAIK. Not every, in TC39.
(I personally dislike the existence of SameValueZero, and would rather stick with SameValue. But I have no reasonable arguments from practicality, only theoretical purity, and so I don't anticipate convincing anyone.)
We should look at this again. The newest thing is the one to cast a colder eye at.
Object.isz = (x, y) => x === y || Object.is(x, y);
2013/12/23 Brendan Eich <brendan at mozilla.com>
You are reasoning from general to particular, but without any reason to focus on the particular of redefining a non-writable property from -0 to +0 or vice versa. There is no use-case "there" there! I bet Mark would find that a subtle security problem.
On the topic of +0, -0 and use cases... Is it still intended that Map and Set will distinguish between these two values? I'm not sure what the use case would be but I fear the consequences. Further elaborated in < esdiscuss/2012-December/026794>.
From: Brendan Eich [mailto:brendan at mozilla.com]
No one is discussing changing === and !==, AFAIK. Not every, in TC39.
To clarify, I was talking about previous discussions where (IIRC) some hoped to move Array.prototype.indexOf
to SameValue. Those were abandoned for compatibility reasons, but I was wondering if it would be possible to move indexOf
(and case
matching, perhaps) to SameValueZero. Sounds like "probably no," in any case.
No, Map and Set will equate -0 and +0.
On Sun, Dec 22, 2013 at 3:28 PM, Brendan Eich <brendan at mozilla.com> wrote:
Domenic Denicola wrote:
If the belief is truly that SameValueZero is more useful than SameValue, perhaps we should consider relaxing that restriction, and allowing people to flip the sign of non-writable zero-valued properties?
You are reasoning from general to particular, but without any reason to focus on the particular of redefining a non-writable property from -0 to +0 or vice versa. There is no use-case "there" there! I bet Mark would find that a subtle security problem.
Yes, it opens an overt communications channel through allegedly frozen state.
2013/12/23 Mark S. Miller <erights at google.com>
No, Map and Set will equate -0 and +0.
\o/
Filed a bug
On Sun, Dec 22, 2013 at 6:41 PM, Mark S. Miller <erights at google.com> wrote:
No, Map and Set will equate -0 and +0.
In SpiderMonkey's Set and Map:
var s = new Set([-0, +0]);
s.size; // 2
var m = new Map();
m.set(-0, 1);
m.set(+0, 2);
m.get(-0); // 1
m.get(+0); // 2
An HTML attachment was scrubbed... URL: esdiscuss/attachments/20131223/299e1d8d/attachment
Chrome Canary behaves similarly (with the difference that the Set constructor can't convert an array), Olov reported an issue: code.google.com/p/v8/issues/detail?id=3069
This is probably just code based on non-recent drafts as not equating them would be bad for reasons Olov outlined in his post.
Why WeakMap/WeakSet continue differentiating between +0 and -0?
Alex Kocharin wrote:
Object.is()
looks like a perfect function for checking oddballs (-0
,NaN
) if you want to represent an arbitrary data correctly. In that case distinguishing signed zeroes is a big plus
or absolutely required.
(making
(-0).toString() === '-0'
would be better though).
(Not backward compatible -- no one is going to risk this for so little gain.)
Mark S. Miller wrote:
Object.isz = (x, y) => x === y || Object.is(x, y);
Not bad.
23.12.2013, 05:59, "Brendan Eich" <brendan at mozilla.com>:
Alex Kocharin wrote:
(making
(-0).toString() === '-0'
would be better though).(Not backward compatible -- no one is going to risk this for so little gain.)
That's something I never really understood when I was reading ES5 spec, where -0 is a special case, and a sole reason why x === Number(String(x))
is not true for all numbers.
Why isn't it stringified as "-0"? How did that happen? Do somebody really check if something is less than zero using "-" in string representation?
Alex Kocharin wrote:
That's something I never really understood when I was reading ES5 spec, where-0 is a special case, and a sole reason why
x === Number(String(x))
is not true for all numbers.Why isn't it stringified as "-0"? How did that happen? Do somebody really check if something is less than zero using "-" in string representation?
That goes back to ES1, not ES5, and probably to the ur-JS implementation (Mocha, in Netscape 2). And it arose due to same outcome in C sprintf, snprintf, etc.
No language stringifies -0 as "0" that I know of. IIRC, IEEE-754 recommends against doing that. Stringizing is not for serialization, rather for human consumption in general, and -0 === 0.
IMPORTANT TYPO ALERT!
Brendan Eich wrote:
No language stringifies -0 as "0"
I meant "-0".
that I know of. IIRC, IEEE-754 recommends against doing that. Stringizing is not for serialization, rather for human consumption in general, and -0 === 0.
... jetlagged again, at least it is for vacation this time...
On 23 December 2013 03:17, Alex Kocharin <alex at kocharin.ru> wrote:
That's something I never really understood when I was reading ES5 spec, where -0 is a special case, and a sole reason why
x === Number(String(x))
is not true for all numbers.
NaN is another special case. IEEE equality is just broken,
Why isn't it stringified as "-0"? How did that happen? Do somebody really check if something is less than zero using "-" in string representation?
Lacking true integers, that would break JavaScript's poor man's emulation of arrays.
Andreas Rossberg wrote:
NaN is another special case. IEEE equality is just broken,
... in your hardware, all of it.
Standards from the last days of Disco, like Disco, will never die.
Lacking true integers, that would break JavaScript's poor man's emulation of arrays.
C'mon, that's not the reason. Hardly anyone generates -0
as an index and
expects it to index a[0]
for some array a
. Things to complain about! :-P
On 7 January 2014 15:28, Brendan Eich <brendan at mozilla.com> wrote:
Standards from the last days of Disco, like Disco, will never die.
Yes. Yet there is no reason why languages keep using it as the generic equality on floats. It could be a separate operator. Especially since comparing floats for equality is disadvised against anyway...
C'mon, that's not the reason. Hardly anyone generates
-0
as an index and expects it to indexa[0]
for some arraya
. Things to complain about! :-P
It's not all that difficult to accidentally create a -0
when you do
pure "integer" arithmetic with floats. I'm pretty sure it would be a
major pitfall. Wasn't that the reason why we changed Map
?
Andreas Rossberg wrote:
It's not all that difficult to accidentally create a
-0
when you do pure "integer" arithmetic with floats. I'm pretty sure it would be a major pitfall. Wasn't that the reason why we changedMap
?
Maybe, and I'm not thrilled about that change, but Map
is new, and
different from Array
or array-likes anyway (value to value mapping).
My point was Array
indexing is the least of our concerns. Changing
(-0).toString()
will probably break tons of code, including numeric form
code, even if only showing "-0"
to users who want "0"
.
The use case for
Object.is()
that I see is to have a version of===
, as a function, that allows one to detect/search forNaN
. For that use case, distinguishing+0
and-0
seems problematic (they are equated almost everywhere else). Should they really be distinguished byObject.is()
?