Say I have the following objects in Javascript:
var a = { xxx: 33 };
var b = { xxx: 33 };
var c;
c = a;
What is the Javascript test that will tell me whether I am dealing with the same object instance? In other words, it should return false for a and b, b and c, but true for a and c.
You just need this
if(c == a) {
// same instance
}
a == b and b == c will return false
Just a standard equality test:
( a == c ) // true
( a == b ) // false
I know the question is about checking if two objects are the same instance but this thread will not be complete without the following.
If you are after checking whether 2 objects are the same, a double equal == is enough. However, for value types (primitives), you may be in a for surprise. Check out the following:
var a = 1; // Integer 1
var b = '1' // String '1'
if (a == b) console.log('Same.');
else console.log('Not same.');
Above will print Same.. To avoid that, use the triple equal === which means two things:
Are they the same value?
Are they the same type?
Or you can use Object.is method like Object.is(a, b).
if (a === b) console.log('Same.');
else console.log('Not same.');
if (Object.is(a, b)) console.log('Same for Object.is.');
else console.log('Not same for Object.is.');
Above will print Not same. and Not same for Object.is..
Some More Info
Below is some more information which has been copy/pasted from this article:
Which operation you choose depends on what sort of comparison you are looking to perform. Briefly:
double equals (==) will perform a type conversion when comparing two things, and will handle NaN, -0, and +0 specially to conform to IEEE 754 (so NaN != NaN, and -0 == +0);
triple equals (===) will do the same comparison as double equals (including the special handling for NaN, -0, and +0) but without type conversion; if the types differ, false is returned.
Object.is does no type conversion and no special handling for NaN, -0, and +0 (giving it the same behavior as === except on those special numeric values).
Note that the distinction between these all have to do with their handling of primitives; none of them compares whether the parameters are conceptually similar in structure. For any non-primitive objects x and y which have the same structure but are distinct objects themselves, all of the above forms will evaluate to false.
Conclusion
My two cents on this would be to get into the habit of always using triple equals === because it cannot hurt you but double equals == can indeed hurt you. You may use double equals == when you just care about the value and the thing you are comparing are primitives; but even this is discouraged because it mostly means a flaw in design. Languages like TypeScript will even avoid that i.e. comparing a '1' to 1 without being explicit about it.
Related
When I run this in node I get the following result. Why?
//Why does this code return the results that it does?
function isBig(thing) {
if (thing == 0 || thing == 1 || thing == 2) {
return false
}
return true
}
isBig(1) // false
isBig([2]) // false
isBig([3]) // true
The == operator in JavaScript converts its operands into a common type before checking for equality (that's why it is recommended always to use the === operator, which respects the types).
In your case the common type is number, so the each given array is converted into a number. For a single element array the conversion into a number results in the single element (converted to a number).
The parameter [2] equals the number 2, so return false.
[3] on the other hand does neither equal 0, 1, or 2, so return true.
See also https://www.w3schools.com/js/js_type_conversion.asp for more examples.
== compares equity loosely.
To quote developer.mozilla.org
Loose equality compares two values for equality, after converting both values to a common type.
This means that [2] == 2 is true it also means "2" == 2 is true
and it's why it is so often recommended to use strict equality so that [2] === 2 is false unless you are really looking for the conversion.
To piggy back on what Mark_M said when you pass the [2] and [3] to the function it's treating them as object literals instead of numbers. Then in your function call its typecasting them for the comparison.
console.log(typeof(1));
console.log(typeof[2]);
console.log(typeof[3]);
In javascript, which will be better way to check conditional statement in terms of performance, robustness and which is the best practice?
var x = null;
// this condition is checked frequently and x will be set to null or some value accordingly
if(x !== null){...}
OR
if(!!x){...}
You could just do
if (x) { ... }
Simply says, if x is a truthy value.
As Nina pointed out. I would always add some extra validation, depending on what I'm expecting.
if (x && x > 0) { ... }
Or
if (x && x instanceof Array)
But I'm always checking x has some sort of value and isn't undefined or null
It's never necessary to write if(!!x){...}. That is exactly the same thing as writing if(x){...}. Using the ! operator twice converts a value to a boolean that reflects whether it is "truthy" or not. But the if statement does that anyway: it tests whether the value you provide is "truthy". So whether you use !! or not it will do the same thing.
if(x !== null){...} is something else entirely. It doesn't just check whether x is "truthy", it specifically compares the value of x with null. For example, if x has the numeric value 0, if(x){...} or if(!!x){...} will not execute the ... code, because 0 is a "falsy" value, but if(x!==null) will execute the ... code, because 0 is not the same value as null.
A related example is if(x!=null){...} or if(x==null){...}. (Note the use of != or == instead of !== or ===.) This is a bit of a special case in JavaScript. When you compare against null using the != or == operator, it actually compares against either null or undefined and treats those two values the same. In other words, if x is either null or undefined, then if(x==null){...} will execute the ... code, but if(x!=null){...} will not execute the ... code.
It's generally recommended to avoid the == and != operators and use the strict comparison === or !== instead, but treating null and undefined the same can be useful in some situations, so this is a case where the non-strict operators are helpful.
In any case, the real question to ask is what is the purpose of your code, and what specifically do you need to test for here?
Assuming you need to check for a value which is strict inequality !== to null
this condition is checked frequently and x will be set to null or some value accordingly
if (x !== null) { /* */ }
Then you can only use the above comparison. Any other comparison would return a wrong result.
For example
var x = 0;
if (x !== null) { // true
console.log(x + ' !== null');
}
if (x) { // false
console.log(x);
}
// some more checks
console.log(undefined !== null); // true
console.log(undefined != null); // false
Edit: My response was quite wrong which I learned after my conversation with Nina Scholz in her own response to this thread. I updated accordingly.
There are many ways to check values depending on the type you expect to use. Therefore the problem is not so much about performance as it is with correct evaluation. Starting with your examples:
if(x != null)
This will evaluate to false if the value of x is either null or `undefined'.
The next case:
if(!!x)
This is an entirely different operation. It casts the value of x as a boolean, and in most cases if(x) will work the same way. But now, if the value is falsy, like 0, the empty string, the expression returns false. So, if expecting a number, you should check for the zero value:
if(x || (0 === x))
Bear in mind that if x were anything other than an int, the expression returns true.
And the case where you expect a string:
if(x || ('' === x))
Same thing here, if x was, say 12, the expression returns true.
I could go on with lots of examples. Unfortunately there are certain expressions that work in unexpected ways. For instance, it should be easy to check if a value is a number by calling isNaN(number), but if the value is an empty string or a representation of an array index ('2'), isNaN returns false.
I recommend you to check this table with all the type conversions so that you become more aware on how to check the validity of a value.
I saw this question here and now I'm curious. How does the is operator behave in python in comparison to the === sign in JS?
No, they are not the same. is in Python checks if two objects have the same id in Python, ie. they are the same, even in memory. Something you can do to check is this:
>>> a='foo'
>>> a is 'foo'
True
>>> id(a)
44434088
>>> id('foo')
44434088
>>> a=[1]
>>> a is [1]
False
>>> id(a)
45789792
>>> id([1])
4469824
In Javascript, the == operator will do implicit type conversion when comparing for equality so, for instance, [] == "" will return true. The === operator is used to check equality without type conversion ([] === "" returns false.)
In Python, the is keyword checks reference equality. So x is y will only return true if x and y both point to the same object in memory. For instance:
x = [1, 2, 3]
y = [1, 2, 3]
z = x
x is y # False
x is z # True
Some gotchas that may result from this are the suggested check for null, x is None. None always points to the same space in memory, so you can be assured that x is None will always return True if x has a None value (and False otherwise).
You may also come across some quirks, like the following:
x = 1
y = 1
x is y # True
The above is a result of a non-standard behaviour in CPython (the Python interpreter you're probably using) where small integers are all assigned to specific objects when the program starts up. You can check that this doesn't work for larger numbers:
x = 1000
y = 1000
x is y # False
Unless you're checking for None or if you specifically want to make sure two variables are pointing to the same location in memory, you should use == instead of is.
No. is in Python is seemingly much stricter than === in JS.
In JS:
For value types (numbers): a === b returns true if a and b have the
same value and are of the same type
For reference types: a === b returns true if a and b reference the
exact same object
For strings: a === b returns true if a and b are both strings and
contain the exact same characters
In Python:
Without contradiction, except id(obj1) is the same as id(obj2), both objects are not identical, and obj1 is obj2 will evaluate to False.
When I compare undefined and null against Boolean false, the statement returns false:
undefined == false;
null == false;
It return false. Why?
With the original answer pointing to the spec being deleted, I'd like to provide a link and short excerpt from the spec here.
http://www.ecma-international.org/ecma-262/5.1/#sec-11.9.3
The ECMA spec doc lists the reason that undefined == false returns false. Although it does not directly say why this is so, the most important part in answering this question lies in this sentence:
The comparison x == y, where x and y are values, produces true or false.
If we look up the definition for null, we find something like this:
NULL or nil means "no value" or "not applicable".
In Javascript, undefined is treated the same way. It is without any value. However, false does have a value. It is telling us that something is not so. Whereas undefined and null are not supposed to be giving any value to us. Likewise, there is nothing it can convert to for its abstract equality comparison therefore the result would always be false. It is also why null == undefined returns true (They are both without any value). It should be noted though that null === undefined returns false because of their different types. (Use typeof(null) and typeof(undefined) in a console to check it out)
What I'm curious of though, is that comparing NaN with anything at all will always return false. Even when comparing it to itself. [NaN == NaN returns false]
Also, another odd piece of information: [typeof NaN returns "number"]
Strict Equality
If possible, you should avoid using the == operator to compare two values. Instead use === to truly see if two values are equal to each other. == gives the illusion that two values really are exactly equal when they may not be by using coercion. Examples:
5 == "5" is true
5 === "5" is false
"" == false is true
"" === false is false
0 == false is true
0 === false is false
From the incomparable MDN, sponsored by the company of JavaScript's creator.
JavaScript provides three different value-comparison operations:
strict equality (or "triple equals" or "identity") using ===,
loose equality ("double equals") using ==,
and Object.is (new in ECMAScript > 6).
The choice of which operation to use depends on what sort of
comparison you are looking to perform.
Briefly, double equals will perform a type conversion when comparing
two things; triple equals
will do the same comparison without type conversion (by simply always
returning false if the types differ); and Object.is will behave the
same way as triple equals, but with special handling for NaN and -0
and +0 so that the last two are not said to be the same, while
Object.is(NaN, NaN) will be true. (Comparing NaN with NaN
ordinarily—i.e., using either double equals or triple equals—evaluates
to false, because IEEE 754 says so.) Do note that the distinction
between these all have to do with their handling of primitives; none
of them compares whether the parameters are conceptually similar in
structure. For any non-primitive objects x and y which have the same
structure but are distinct objects themselves, all of the above forms
will evaluate to false.
For a visual overview of the whole picture of equality in JavaScript:
https://dorey.github.io/JavaScript-Equality-Table/
The truth is, this seemingly "bad" aspect of JavaScript is a source of power when you understand how it works.
So undefined really means undefined. Not False, not True, not 0, not empty string. So when you compare undefined to anything, the result is always false, it is not equal to that.
You question is half, as we compare undefined/ null to any other types.
we will have false return.
There is no coercion happening, even we are using == operator.
This is so because it is so. :)
Read the ECMA standards here: https://www.ecma-international.org/ecma-262/5.1/#sec-11.9.3
Undefined is not the same thing as false, false is a boolean object (which has a value of 0 therefore it is indeed defined).
An example:
var my_var;
var defined = (my_var === undefined)
alert(defined); //prints true. It is true that my_var is undefined
my_var = 22;
defined = (my_var === undefined)
alert(defined); //prints false. my_var is now defined
defined = (false === undefined)
alert(defined); //prints false, false is defined
defined = (true === undefined)
alert(defined); //prints false, true is defined
According to the specification flow:
If Type(y) is Boolean, return the result of the comparison x ==
ToNumber(y).
1) undefined == false; -> undefined == Number(false); -> undefined == 0;
2) null == false; -> null == Number(false); -> null == 0;
There is no rule for these cases, so go with the behavior in the last step:
Return false.
Below is a pure function f for which f(a) !== f(b) despite a === b (notice the strict equalities) for some values of a and b:
var f = function (x) {
return 1 / x;
}
+0 === -0 // true
f(+0) === f(-0) // false
The existence of such functions can lead to difficult-to-find bugs. Are there other examples I should be weary of?
Yes, because NaN !== NaN.
var f = function (x) { return Infinity - x; }
Infinity === Infinity // true
f(Infinity) === f(Infinity) // false
f(Infinity) // NaN
Some other examples that yield NaN whose arguments can be strictly equal:
0/0
Infinity/Infinity
Infinity*0
Math.sqrt(-1)
Math.log(-1)
Math.asin(-2)
this behaviour is perfectly ok, because, in mathematical theory, -0 === +0 is true, and 1/(-0) === 1/(+0) is not, because -inf != +inf
EDIT: although I am really surprised that javascript can in fact handle these kinds of mathematical concepts.
EDIT2: additionally, the phenomenon you described is completely based on the fact, that you divide by zero from which you should expect at least some strange behaviour.
1/+0 is Infinity and 1/-0 -Infinity, while +0 === -0.
This can be explained by the fact that ECMA defines -0 to equal +0 as a special case, while in other operations these two values retain their different properties, which result in some inconsistencies.
This is only possible because the language explicitly defines two non-equal values to be equal, that in fact are not.
Other examples, if any, should be based on the same sort of artificial equality, and given http://ecma262-5.com/ELS5_HTML.htm#Section_11.9.6 there is no other such excention, so probably no other example of this.
If it's of any use, we can ensure that 0 is not -0 by adding 0 to it:
var f = function(x) {
return 1 / (x + 0);
}
f(+0) === f(-0)
In ECMAScript 3, another example where === behaves surprisingly is with joined functions. Consider a case like this:
function createConstantFunction(result) {
return function () {
return result;
};
}
var oneReturner = createConstantFunction(1); // a function that always returns 1
var twoReturner = createConstantFunction(2); // a function that always returns 2
An implementation is allowed to "join" the two functions (see §13.2 of the spec), and if it does so, then oneReturner === twoReturner will be true (see §13.1.2), even though the two functions do different things. Similarly with these:
// a perfect forwarder: returns a sort of "duplicate" of its argument
function duplicateFunction(f) {
return function (f) {
return f.apply(this, arguments);
};
}
var myAlert = duplicateFunction(alert);
console.myLog = duplicateFunction(console.log);
Here an implementation can say that myAlert === console.myLog, even though myAlert is actually equivalent to alert and console.myLog is actually equivalent to console.log.
(However, this aspect of ECMAScript 3 was not preserved in ECMAScript 5: functions are no longer allowed to be joined.)
I'm not so sure this is so scary ;-) Javascript is not a pure language and the presence of +/-0 and the equality of -0 and +0 are specific to IEEE-754 and are "well defined", even if perhaps sometimes surprising. (Even NaN != NaN always being true is well defined, for instance.)
From signed zero:
According to the IEEE 754 standard, negative zero and positive zero should compare as equal with the usual (numerical) comparison operators...
Technically, because the two inputs to f are different, then the result can also be different. For what it's worth, Haskell will treat 0 == -0 as true but will treat (1 / 0) == (1 / (-0)) as false.
However, I do find this an interesting question.
Happy coding.
There are many such functions, here is another example
function f (a) {
return a + 1;
}
1 == "1"
but f(1) != f("1")
This is because equality is a nuanced concept.
Perhaps more scary is that in your example -0 === +0.