4

I am looking for a way to check if two variables refer to the same object in javascript.

ex:

var a = {foo:"bar"};
var b = {foo:"bar"};
var aa = a;

testSame(a, b); //false
testSame(a, aa); //true

var r = "a string";
var s = "a string";
var rr = r;

testSame(r, s); //false
testSame(r, rr); //true

So far there doesn't seem to be a way of getting a way of doing this.

edit: testSame() is not a real function it would be the hypothetical solution.

edit: The answer to the question How to check if two vars have the same reference? does not answer this question as it uses the strict equality operator (===) which does not differentiate between between 2 vars pointing to 2 instances of an identical string.

Community
  • 1
  • 1
Coyote
  • 2,454
  • 26
  • 47
  • 2
    ?? Your code is 100% correctly telling you when two variables refer to the same object. What's the problem? – Pointy Jan 31 '17 at 21:03
  • 1
    Also where's the code for `testSame()`? – Pointy Jan 31 '17 at 21:03
  • Under what circumstances would you need to know if two strings are the same object? – Jordan Running Jan 31 '17 at 21:03
  • 1
    Also also: strings aren't objects – Pointy Jan 31 '17 at 21:04
  • you will need to add a unique identifier to the object in order to test for equality. – Justin Herter Jan 31 '17 at 21:07
  • 1
    there is a difference between comparing objects that look the same and objects that have same reference. Question is vague – charlietfl Jan 31 '17 at 21:07
  • @Pointy: no the code shows the solution I am looking for. It seems to be impossible so fat to check if 2 variables refer to the same object. – Coyote Jan 31 '17 at 21:24
  • @charlietfl: I am looking for a way to check if 2 variables refer to the same object. For C I would check if the 2 pointers are equal. I am not sure how I can express this in a clearer way for javascript as there is no concept of pointers. – Coyote Jan 31 '17 at 21:33
  • @Coyote normal `==` and `===` comparisons already **do** tell you whether two variables refer to the same object. In your first piece of code, the variables `a` and `b` are initialized to refer to two **different** objects. – Pointy Jan 31 '17 at 22:57
  • And comparing two identical strings **will** be `true` with either `==` or `===`. Strings are not objects. – Pointy Jan 31 '17 at 22:58

5 Answers5

3

Just comparing with == or === will do the trick, except for strings. There's no way to do what you ask with strings.

var a = {foo:"bar"};
var b = {foo:"bar"};
var aa = a;

testSame(a, b); //false
testSame(a, aa); //true

var r = "a string";
var s = "a string";
var rr = r;

testSame(r, s); // false <-- this will be true
testSame(r, rr); //true

function testSame(a, b) {
  console.log(a === b);
}
Schlaus
  • 18,144
  • 10
  • 36
  • 64
  • So far it seems indeed that there is no way to do that with strings. – Coyote Jan 31 '17 at 21:43
  • @Coyote that's correct — it doesn't even make sense in JavaScript to think of two identical strings as being different. It's exactly like wanting to know whether one variable that's set to the number 5 is different from another variable set to the number 5. – Pointy Jan 31 '17 at 23:02
  • Not quite, think about the module or singleton pattern. What if I want each call to a new Log() to really just return the same Log? inst1 === inst2 gives a way to ensure that this is the case. Otherwise I see no reason though. – Joshua Hedges May 23 '18 at 20:09
3

The question is correct, but there is a trick in it. The following console code snippet reveals it:

const A = "abc", B = new String(A), C = B

> A == B
true

> A === B
false

> B === C
true

Variable A refers integral primitive that is converted to String object on a demand. JS machine may optimize references to equal primitive strings defined in the code to target exactly the same block of RAM — that's why the question, as defined, has no solution.

You need to manually wrap each integral value to corresponding object class: String, Number, Boolean, — and test them with === operator:

var r = new String("a string");
var s = new String("a string");
var rr = r;

I've applied this trick to track the initially empty controlled input in React, — whether the user had edited it and then erased to be clear, — without involving additional field in the state.

2

Here's how things work. First, in this code:

var a = {foo:"bar"};
var b = {foo:"bar"};

the variables a and b are initialized with references to two different objects. Thus comparisons with either == or === will report them as being different (i.e., not equal).

Here, however:

var a = "some string";
var b = "some string";

the two variables are initialized to refer to strings that are identical. String values in JavaScript are not objects — they're primitives. Comparisons between a and b with either == or === will therefore return true because the strings are the same. This is exactly the same as things would have been if the variables had been initialized like this:

var a = 17;
var b = 17;

Numbers and strings are primitives, so comparison compares the semantic values of the primitives. Objects, however, are not primitives, and comparison of objects is based on object identity.

It literally is nonsensical in the JavaScript semantic domain to want to know whether two variables pointing to the same identical string refer to two different expressions of that same string, in precisely the same way as it would be nonsensical to want to know whether one 17 were different from another.

Pointy
  • 405,095
  • 59
  • 585
  • 614
  • 1
    "It literally is nonsensical ..." Ah, yet I find myself wanting to know exactly that, in order to determine if when using strings as keys in objects or Maps, the result of iterating the keys shows they are pointing to the same location in memory as the original string they were created with. I have a situation where I am creating many objects using very long strings as keys, and want to know if I am essentially holding duplicate strings in memory. – KevinHJ Sep 25 '20 at 20:00
  • What you say may be true for production, but for development it would be very handy for me right now to know this. – KevinHJ Sep 25 '20 at 20:01
  • @Allasso whether or not a particular JavaScript runtime "condenses" identical strings into a single string internally is not knowable through standard JavaScript APIs. – Pointy Sep 25 '20 at 20:17
  • Oh, I don't dispute that. I just find myself dreaming of a ==== operator for strings right now. But what you're probably pointing out is that even that may not be conclusive, as one might not know whether a true result is a consequence of the implementation and is reliable, or if it is just a consequence of optimization and may not always happen. – KevinHJ Sep 25 '20 at 20:30
0

This one is already answered in this question: How to check if two vars have the same reference?

The short version use === instead of ==

Community
  • 1
  • 1
  • No it isn't as `r === s` returns `true` instead of `false`. – Coyote Jan 31 '17 at 21:21
  • But r and s are identical objects the === checks if the objects are identical and of the same type. But what is the purpose of checking if the objects are identical? That is the main question; – Stef van den Berg Jan 31 '17 at 21:27
0

As I understand it, === checks the identity of the object. Javascript's strings are immutable, so when you say

var x = "string"
vay y = "string"

x and y are actually referencing the same object in memory. So, unfortunately, what you want is impossible. Symbols provide this functionality:

Symbol('x') === Symbol('x') // => false
quinn
  • 5,508
  • 10
  • 34
  • 54