JavaScript implement two type of comparisons: by value and type, and only by value. What it means?. Let's explain these two comparisons using string values:
var str1 = "asdf";
var str2 = "asdf";
var str3 = new String("asdf");
var str4 = new String("asdf");
1. console.log(str1 == str2); // Prints true
2. console.log(str1 === str2); // Prints true
3. console.log(str1 == str3); // Prints true
4. console.log(str1 === str3); // Prints false
5. console.log(str1 == str4); // Prints true
4. console.log(str1 === str4); // Prints false
6. console.log(str3 == str4); // Prints false
7. console.log(str3 === str4); // Prints falseJavaScript provides two comparison operators for these two types of comparison: equal (==) and strict equal (===).
The equals operator == compares by value. This mean that during the evaluation JavaScript doesn't care about the variable type but in the content. The inquiring readers should be asking themselves: is it possible to determine a variable content without checking the type?. And the answer once again is yes, it is. All objects in JavaScript have a primitive method named valueOf(). When you are comparing two variables by value (using ==), the engine call this method for both operands, and compares the result. Let's see this weird example:
var str1 = "asdf";
var arr1 = new Array();
arr1.valueOf = function () {
return "asdf";
};
console.log(str1 == arr1);Against all probabilities this piece of code will print true. Why??, we are comparing a string against an array!!. Yes, but during a value comparison the type, believe me, doesn't care.
Okay, your mind is now looking for ways to explode this potential bug, but we are not careless coders, right?. So let's go to check the other comparison operator: strict equal (===).
Comparing by type and value means that the variable type and the value must be equals. This kind of comparison is not stronger only for the extra (type) validation, but because the engine performs reference validation. Yes, another example here:
var str1 = new String();
var str2 = new String();
str1.valueOf = function () {
return "asdf";
};
str2.valueOf = function () {
return "asdf";
};
1. console.log(
(str1.valueOf() == str2.valueOf()) &&
(typeof str1 == typeof str2)
);
2. console.log(str1 === str2);If we try to emulate the engine behavior (as we shown with the == operator) it will fail. In the case (1) the output will be true because it matches our definition: "compares type and value". But the engine performs the extra reference validation and that's why the case (2) will print false.
Of course, as the primitive types (Boolean, String and Number) are immutable objects (their type and values are always unique) and they are the wide-used kind of objects, we often can't take care about this tricky and dangerous behavior.
The last example bring us to the last point of this post: the typeof operator. The typeof operator can be used followed of any variable and it returns a string indicating the primitive type of the variable's value.
var bool1 = true;
var str1 = "asdf";
var num1 = 1234;
var obj1 = {};
var arr1 = [];
console.log(typeof bool1); // Prints 'boolean'
console.log(typeof str1); // Prints 'string'
console.log(typeof num1); // Prints 'number'
console.log(typeof obj1); // Prints 'object'
console.log(typeof arr1); // Prints 'object'All returned strings are part of the ECMAScript standard, so we are able to use it for validations. But let's focus in the last result from the example:
console.log(typeof arr1); // Prints 'object'
You may be wondering why it prints "object" if the value is an array. Sadly (or not) the ECMAScript standard just defines typeof-results for the primitive types, which are: Boolean, String and Number. Any other kind of value will be interpreted as an object (objects are commonly named "composite types"), and evidently an array is not a primitive type so it's an object.
There's another dangerous behavior with typeof: the primitive types are also constructors which can be used to create objects containing primitive values. For example:
var str1 = "asdf";
var str2 = new String("asdf");
console.log(typeof str1); // Prints 'string'
console.log(typeof str2); // Prints 'object'Yes, if you create an instance of the String prototype it will be an object, not a primitive string. The more confusing point there is that using the == operator str1 and str2 are equals, but not comparing them with ===.
Okay, stop it. We have a lot of information up to there. Don't be afraid, the comparison difference between primitive types and objects created using the primitive constructors can be unified, but there will be another evilness chapter explaining how the instanceof operator works in JavaScript.
From my point of view, the strict equals must be used whenever we're comparing two values from an unknown source, it is, the most of cases. Leave the equal (==) operator to special and conscious uses.
Good look.
No comments:
Post a Comment