1

As of the Summer '17 release, I'm not able to compare values with the === operator due to the get function returning Proxy objects. Take the following example

var array = [1,2,3];
cmp.set('v.array', array);
cmp2.set('v.array', array);
cmp.get('v.array') === cmp2.get('v.array'); //returns false;

Has anyone encountered this or found a workaround?

1 Answer 1

2

In JavaScript, each Proxy() instance has its own identity different from all other Proxy() objects and from the object proxied. When applied to two objects, he equality operators == and === compare the object references, and the consequence is that:

  1. Comparing distinct proxies returns false even though the underlying target is the same.
  2. An unwrapped target object is not equal to any of its proxies.

You are witnessing a known technological limitation. Alternatives have been suggested such as the implementation of proxy-aware equality functions like Proxy.isEqual() and Proxy.isIdentical() to replace all uses of == and === respectively, but this makes the code less portable because you have to modify the application.

Could I can suggest this as a workaround? Use JSON.stringnifY() which could have some benefits:

var array1 = [1,2,3];
cmp.set('v.array1', array1);

var array2 = [1,2,3];
cmp.set('v.array2', array2);

var F = JSON.stringify;
console.log(
    array1 == array2, //returns false 
    array1 === array2, //returns false 
    F(array1) === F(array2), //returns true 
    F(cmp.get('v.array1')) === F(cmp.get('v.array2')) //returns true;
);      

As you can see, you can enable identity based on the content of the object, no matter its origin. While array1 and array2 have the same content, they are not identical.

Maybe comparing the content is more desirable in your app?

4
  • Thank you for taking the time to make such a detailed response. I have considered the JSON approach. My only concern is that sometimes I have arrays of objects, and to my knowledge, since property order isn't guaranteed, this could result in incorrect falsehoods. I could work around that though. I have large datasets in aura:iterations and have been borrowing from the react/immutable concepts to avoid doing unnecessary sets of arrays if data doesn't change. I think my next steps are to do some performance test with JSON stringify, and other manual equality checks to see what I can get.
    – wellmstein
    Jun 12, 2017 at 19:28
  • There are versions of sorted JSON you could import... but here is something else to consider: the ultimate goal of the comparison is to check whether something has changed. You could use methods to pass arguments between components, and then act appropriately in the method callback?
    – JF Paradis
    Jun 12, 2017 at 19:59
  • That's essentially what I have. (oversimplified in the original post for brevity). Basically cmp1 and cmp2 don't know about each other. They just know they care about array1. Furthermore, cmp2 might only care about about array1[5].foo. Everyone registered on cmp3 which managed the full state and cmp1/cmp2 just reacted to changes there. The === check with the rule of "dont mutate anything" made it easy to communicate around my app. Anyway - I wrote a equals() that does a few quick checks then falls back on json. Seems to be fast enough at this point. Thanks for the help!
    – wellmstein
    Jun 12, 2017 at 21:28
  • You can read more about the problem with Proxy() here, if you are so inclined: matthias-keil.de/papers/pos2013-proxy.pdf
    – JF Paradis
    Jun 13, 2017 at 18:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.