Proposal: [Symbol.equals]

Jordan Harband ljharb at gmail.com
Sat Jan 19 05:32:37 UTC 2019


This thread would apply equally well to objects (there's no such thing as a
"json object" - json is a string, and once it's parsed into an object it's
not json anymore) as to classes.

Please stop derailing threads with your off-topic ideology about how to
write code - that belongs in a style guide, or in your own project, but not
here.

On Fri, Jan 18, 2019 at 9:28 PM kai zhu <kaizhu256 at gmail.com> wrote:

> the most reliable/idiot-proof equality is by avoiding classes altogether;
> stick with plain json-objects and compare their
> canonical-json-representation like this real-world example [1]:
>
> ```
> /*jslint devel*/
> (function () {
>     "use strict";
>     var jsonStringifyCanonical;
>
>     jsonStringifyCanonical = function (obj, replacer, space) {
>     /*
>      * this function will JSON.stringify <obj>,
>      * with object-keys sorted and circular-references removed
>      */
>         var circularSet;
>         var stringify;
>         var tmp;
>         stringify = function (obj) {
>         /*
>          * this function will recursively JSON.stringify obj,
>          * with object-keys sorted and circular-references removed
>          */
>             // if obj is not an object or function,
>             // then JSON.stringify as normal
>             if (!(
>                 obj
>                 && typeof obj === "object"
>                 && typeof obj.toJSON !== "function"
>             )) {
>                 return JSON.stringify(obj);
>             }
>             // ignore circular-reference
>             if (circularSet.has(obj)) {
>                 return;
>             }
>             circularSet.add(obj);
>             // if obj is an array, then recurse its items
>             if (Array.isArray(obj)) {
>                 tmp = "[" + obj.map(function (obj) {
>                     // recurse
>                     tmp = stringify(obj);
>                     return (
>                         typeof tmp === "string"
>                         ? tmp
>                         : "null"
>                     );
>                 }).join(",") + "]";
>                 circularSet.delete(obj);
>                 return tmp;
>             }
>             // if obj is not an array,
>             // then recurse its items with object-keys sorted
>             tmp = "{" + Object.keys(obj).sort().map(function (key) {
>                 // recurse
>                 tmp = stringify(obj[key]);
>                 if (typeof tmp === "string") {
>                     return JSON.stringify(key) + ":" + tmp;
>                 }
>             }).filter(function (obj) {
>                 return typeof obj === "string";
>             }).join(",") + "}";
>             circularSet.delete(obj);
>             return tmp;
>         };
>         circularSet = new Set();
>         return JSON.stringify((
>             (typeof obj === "object" && obj)
>             // recurse
>             ? JSON.parse(stringify(obj))
>             : obj
>         ), replacer, space);
>     };
>
>     // true
>     console.assert(
>         // {"data":{"x":1,"y":2,"z":3},"meta":{"label":"point #13"}}
>         jsonStringifyCanonical({
>             data: {x: 1, y: 2, z: 3},
>             meta: {label: "point #32"}
>         })
>         // === {"data":{"x":1,"y":2,"z":3},"meta":{"label":"point #13"}}
>         === jsonStringifyCanonical({
>             meta: {label: "point #32"},
>             data: {z: 3, y: 2, x: 1}
>         })
>     );
> }());
> ```
>
>
> [1] testing aa “==“ b by comparing their canonical json-representation
> https://github.com/kaizhu256/node-utility2/blob/2018.12.30/test.js#L2903
>
> https://github.com/kaizhu256/node-utility2/blob/2018.12.30/lib.utility2.js#L2760
>
>
> On 18 Jan 2019, at 3:39 PM, Isiah Meadows <isiahmeadows at gmail.com> wrote:
>
> Yeah, I agree. I'd suggest overloading `==`, but that'd risk serious web
> compat issues, especially if `null`/`undefined` aren't special-cased. I
> feel an `equals` instance method added to all builtins and an
> `Object.equals` attempting that method first before performing a shallow
> object comparison would be the best solution.
> On Fri, Jan 18, 2019 at 15:24 Jordan Harband <ljharb at gmail.com> wrote:
>
>> It's pretty important that the meaning `===` not be able to change.
>>
>> On Fri, Jan 18, 2019 at 10:33 AM ViliusCreator <
>> viliuskubilius416 at gmail.com> wrote:
>>
>>> What about having Symbol.equals?
>>>
>>> For example, for now this is what it does:
>>>
>>> ```js
>>>
>>> class Position {
>>>     constructor(o) {
>>>         this.x = o.x instanceof Number ? o.x : 0
>>>
>>>         this.y = o.y instanceof Number ? o.y : 0
>>>
>>>         this.z = o.z instanceof Number ? o.z : 0
>>>     }
>>> }
>>> console.log(new Position({x: 10, y: 10, z: 10}) === new Position({x: 10,
>>> y: 10, z: 10})
>>>
>>> ```
>>> Output is of course, false.
>>> With `Symbol.equals`, we could make it easier, instead of
>>> `instance.equals(otherInstance)`.
>>>
>>>
>>>
>>> For example:
>>>
>>> ```js
>>>
>>> class Position {
>>>
>>>     [Symbol.equals](oIn) {
>>>         return oIn.x === this.x && oIn.y === this.y && oIn.z === this.z
>>>     }
>>>     constructor(o) {
>>>         this.x = o.x instanceof Number ? o.x : 0
>>>
>>>         this.y = o.y instanceof Number ? o.y : 0
>>>
>>>         this.z = o.z instanceof Number ? o.z : 0
>>>     }
>>> }
>>> console.log(new Position({x: 10, y: 10, z: 10}) === new Position({x: 10,
>>> y: 10, z: 10})
>>>
>>> ```
>>> Now output would be true.
>>>
>>> This would save most of the time, instead of writing .equals and then
>>> surrounding everything with ().
>>>
>>>
>>> <https://www.avast.com/sig-email?utm_medium=email&utm_source=link&utm_campaign=sig-email&utm_content=emailclient> Virus-free.
>>> www.avast.com
>>> <https://www.avast.com/sig-email?utm_medium=email&utm_source=link&utm_campaign=sig-email&utm_content=emailclient>
>>> _______________________________________________
>>> 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
>>
> _______________________________________________
> 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/20190118/5a33f5ee/attachment.html>


More information about the es-discuss mailing list