Proposal: [Symbol.equals]
kai zhu
kaizhu256 at gmail.com
Sat Jan 19 07:07:48 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.
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 <mailto: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/test.js#L2903>
> https://github.com/kaizhu256/node-utility2/blob/2018.12.30/lib.utility2.js#L2760 <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 <mailto: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 <mailto: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 <mailto: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 <mailto:es-discuss at mozilla.org>
>> https://mail.mozilla.org/listinfo/es-discuss <https://mail.mozilla.org/listinfo/es-discuss>
>> _______________________________________________
>> es-discuss mailing list
>> es-discuss at mozilla.org <mailto:es-discuss at mozilla.org>
>> https://mail.mozilla.org/listinfo/es-discuss <https://mail.mozilla.org/listinfo/es-discuss>
>> _______________________________________________
>> es-discuss mailing list
>> es-discuss at mozilla.org <mailto:es-discuss at mozilla.org>
>> https://mail.mozilla.org/listinfo/es-discuss <https://mail.mozilla.org/listinfo/es-discuss>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20190119/93fcd768/attachment-0001.html>
More information about the es-discuss
mailing list