Proposal: [Symbol.equals]

Jordan Harband ljharb at gmail.com
Sat Jan 19 17:10:53 UTC 2019


As has been stated many times before, many JS developers have been hired to
do things entirely unrelated to UX workflows; regardless, whether you like
a specific coding style or not is *irrelevant* to discussing language
features, and is very disruptive to these discussions. Please confine that
to discussing style with your own team, or within a styleguide.

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

> > 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.
>
> i’m not so sure when you start having classes with
> getters/setters/private-fields.  then people begin digging
> rabbit-holes/silos trying to solve low-level equality-issues that shouldn’t
> even exist, and overall lose focus of the big-picture UX-workflow problems
> most of us js-devs were originally hired to solve.
>
> On 18 Jan 2019, at 11:32 PM, Jordan Harband <ljharb at gmail.com> wrote:
>
> 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/20190119/dd614112/attachment-0001.html>


More information about the es-discuss mailing list