Hi Brad I’m new to Qt Quick and while I’ve been learning the QML scripting language I’ve noticed that often in coding examples I’ve seen people use three equals signs when comparing values instead of two. What the heck is that?
The comparison operators which use three characters vs. two are called the Strict Comparison Operator and is not new to QML but rather part of the ECMAScript standard.
In ECMAScript there are two types of compactors; strict (===) and type-converting or non-strict (==).
Type-Converting or Non-Strict Comparison
When using non-strict comparisons the operands are implicitly converted to the same types then compared using strict comparison once the types match.
console.log( 1 == 1 ); //True console.log( "1" == 1 ); //True console.log( '1' == 1 ); //True console.log( 0 == false ); //True console.log( null == undefined ); //True
In the above all the comparisons return true because they are all converted to the same types implicitly. What is being compared is the data not the objects. So in the case of “1” == 1 the left hand side operand is implicitly converted to a Number then compared to the right hand side; Both Numbers being equal results in a true. Some times both the right and left hand operands must be converted into a common primitive type in order to allow for same type strict comparison.
In cases when checking if an object is valid this approach is handy as you don’t have to check against null and undefined explicitly; however, this implicit conversion can result in unexpected performance hits and hard to track down defects. Say you have a function which is looking for an enum value but can, due to EMACScripts duck-typing, also accept a string. If said string has the numerical value of your enum your if statement block will execute and you might not be expecting that. Have you even been working with an EMACScript and found yourself looking at an if statement that no matter what the values are you gave it always evaluated to true? I have and it was this implicit conversion that was the culprit; what do you mean 1 equals 2?!?!?!
When using strict comparison no type conversion is performed and the operands are strictly compared as is. That is if you try to compare a string to an Number that is exactly what will be compared, a string and a Number.
console.log( 1 === 1 ); //True console.log( "1" === 1 ); //False console.log( '1' === 1 ); //False console.log( 0 === false ); //False console.log( null === undefined ); //False
Now that we are using strict comparison notice how the comparisons in the above changed. Now all but the first one are evaluating to false. This is because the types are also being compared. That is a Number does not equal a Boolean therefore 0 does not equal False. By using strict comparison you save yourself the implicit conversion and ensure that no hard to find defects pop up when if statements are comparing strings to enums and evaluating to true unexpectedly.
There is also a strict comparison operator for inequality as well which returns true only if the operands are not equal or do not share the same type.
console.log( "1" !== 1 ); //True console.log( "1" != 1 ); //False
In EMACScript objects are handled differently when they are compared to each other. If you have an object and you are comparing it to a primitive type such as a Boolean, Number, or string primitive then if using non-strict comparison the object is implicitly converted to the primitive type then compared.
var a = new String('foo'); console.log( a == 'foo' ); //True console.log( a === 'foo' ); //False
In the above the toString method is called on the String object to convert it to a string primitive then compared against the right hand operand, which is also a string primitive, resulting in an evaluation of true. If we were to use a strict comparison the evaluation would be false because no implicit conversion is done on the String object thus the types don’t match and the Strict Comparison Algorithm returns false.
If however both the right and left hand operands are objects then since their base type, Object, match then an object comparison is done to see if they are the same object.
var a = new String('foo'); console.log( a == a ); //True console.log( a === a ); //True var b = new String('foo'); console.log( a == b ); //False console.log( a === b ); //False
You can see here that it does not matter what type of comparison we use, strict or non-strict, the comparison only equates to true if we are actually comparing the object to itself; we are comparing the object and not the data.
Well their you have it that is what the three character comparison operation is, a Strict Comparison Operator, and we use it to ensure that we are actually comparing the values we expect without any sort of implicitly conversion unless we support that sort of thing. That is if we need to tell the difference between null and undefined we’d use a strict comparison but if we would consider them the same and handle them in the same way then we could use a non-strict comparison to save us a extra comparison.
Until next time think imaginatively and design creatively