0

Give me one good reason why I shouldn't stop using the third equals.

typeof x === "object"
typeof x == "object" // does the same thing 100% of the time and uses one less character
Hans Z
  • 4,664
  • 2
  • 27
  • 50
user1472219
  • 199
  • 5
  • 9
  • 1
    In general you shouldn't count the number of characters in your code unless if you are google. – Hans Z Jul 09 '12 at 21:06
  • Since there is some argument in the answers about this: are you asking whether or not you should use the third equals *for this particular condition*, or if you should use it *at all*? Because to me this question reads like the latter, but others think it is the former. – KRyan Jul 09 '12 at 21:10
  • i say the question is simply whether or not it should be used in this particular condition and if doing so is a sign of not understanding the purpose of the operator. – user1472219 Jul 09 '12 at 21:11
  • Well, I suppose there's a plenty of answers here already, that say more-o-less the same thing: there's no reason to choose `==` instead of `===` for this case - as they both give you the same result. Some might choose `===` just for all comparisons in his code to be consistent; but there's actually none of the sane reasons to be consistent with `==`. – raina77ow Jul 09 '12 at 21:37
  • 1
    possible duplicate of [JavaScript === vs == : Does it matter which "equal" operator I use?](http://stackoverflow.com/questions/359494/javascript-vs-does-it-matter-which-equal-operator-i-use) – Kendall Frey Jul 09 '12 at 21:39
  • @KendallFrey Damn, I knew it. ) – raina77ow Jul 09 '12 at 21:40
  • Because I literally ended up having to pause on the second one and put in the thinking effort to remember every JavaScript rule relevant to `typeof` and `==` just to check if you're actually right that it does the same thing. That's an expensive snag to hit while trying to figure out or update or fix whatever code this actually appears in. And if you don't find yourself having to pause the same expensive way, you either have it cached (good for you, but not everyone does), have a much more powerful brain (less likely but ditto), or you are just more careless and sloppy than you should be. – mtraceur Sep 06 '22 at 17:22

6 Answers6

4

1 (very) good reason: consistency.

In general you should be as specific as possible. If you are following the general rule that you should be as specific as possible, you should keep it as === for consistency. Plus, assuming you follow the general rule, if you make an exception, then more exceptions will follow, and soon you won't have a general rule.

I'd take consistency and specificity over the hassle of having to type 1 character 100% of the time.

hvgotcodes
  • 118,147
  • 33
  • 203
  • 236
  • I didn't downvote (I never downvote posts if not for some pretty BIG cases), but I actually don't believe in this reason. ) For example, I often use `something != null` construct, and don't have to worry about whether `something` is `null` - or just `undefined`. Does it make my code inconsistent? ) – raina77ow Jul 09 '12 at 21:18
  • well then you should just do if `(something)` or `!!something` ;) – hvgotcodes Jul 09 '12 at 21:21
  • Ahem. ) Do I really have to explain the difference between `something != null` and `(! something)`? ) – raina77ow Jul 09 '12 at 21:22
  • Can't say. Seems like a good answer to me. – David Wolever Jul 09 '12 at 21:27
  • @raina77ow only if I have to explain the difference between `!something` and `!!something` – hvgotcodes Jul 09 '12 at 21:29
  • @raina77ow those are different concepts, and confirm the reason. When you use `!= null` you are *deliberately* using a less specific comparison than `===` - and if you used `===` everywhere that you don't want fuzzy comparisons, then readers of your code can trust that your uses of `==` or `!=` as you *explicitly saying* that this was what you intended. If you use `==` and `!=` for object comparisons generally, then anyone maintaining code after you will have to reverse engineer from context *every time* whether or not the looser behavior was intended and is relied upon. – mtraceur Sep 06 '22 at 17:14
2

In this specific situation, the only advantage of === is that it's slightly faster.

For profiling results, see: http://jsperf.com/equal-performance (specifically, "string + double equals" and "string + tripple equals").

David Wolever
  • 148,955
  • 89
  • 346
  • 502
  • 1
    I also think so, but actually can't find a reason why. ) We compare two values of the same type, why should it be faster? – raina77ow Jul 09 '12 at 21:04
  • I'm not entirely sure why it's faster. But, at least in some browsers, it is (see the jsperf link). – David Wolever Jul 09 '12 at 21:06
  • Its faster because === assumes that the types are the same, and doesn't bother type casting, while == will check to see if they are equal when cast to the same type. For example `1 == "1"` will return true and `1 === "1"` will return false. – Rob Wagner Jul 09 '12 at 21:08
  • @Recursed it's not obvious to me that it's that simple. I would guess that the first check in the implementation of both `==` and `===` would be something like `if (typeof a != typeof b) …`. But it's possible that interpreters don't do that. – David Wolever Jul 09 '12 at 21:10
  • Well, I've just prepared my own jsperf for this specific case, and `== `actually come out of it on top of `===`. So what? ) – raina77ow Jul 09 '12 at 21:13
  • Speaking of casts, don't you think the engine should first check the types of operands - and only after that make a decision about what will be casted and to what? – raina77ow Jul 09 '12 at 21:14
  • @raina77ow could you link to that jsperf? – David Wolever Jul 09 '12 at 21:15
  • ahh i like this. Simple and true +1 – hvgotcodes Jul 09 '12 at 21:18
  • @DavidWolever Here [it is](http://jsperf.com/double-or-triple). – raina77ow Jul 09 '12 at 21:20
  • @raina77ow uuhh… I think you may be mis-reading the results. They show that `===` is either as fast, or faster than, `==`. – David Wolever Jul 09 '12 at 21:26
  • No, I didn't misread the results. ) I've tested in Chrome twice, and the `==` was _faster_, even though by a very little margin. I can give you my word - or a screenshot, if you'd like. But frankly, this is getting stupid. ) – raina77ow Jul 09 '12 at 21:27
  • Ah, please forgive me then. I guess the graph has since changed. This is what I see how: https://img.skitch.com/20120709-x72qfqx1r9gpq7g7tug523q54p.png – David Wolever Jul 09 '12 at 21:29
  • @raina77ow cool, Firefox shows faster than Chrome, that's a first, but yes at least in FF `===` is faster than `==` (but nothing to worry about) – Rodolfo Jul 09 '12 at 21:31
1

You're not comparing object types. You compare strings: the literal one ('object') and that returned by typeof operator.

Because you always will compare strings in this statement, I suppose using == or === will make no difference here.

raina77ow
  • 103,633
  • 15
  • 192
  • 229
  • 1
    he already knows this -- the question is "is there a reason not to use === in this case" – hvgotcodes Jul 09 '12 at 21:16
  • 1
    @hvgotcodes there is no a reason. You can use `===` or `==` when you need. but you should understand the difference. Also in JS there are not so many situations in that you should use `===` instead of `==`. – Sergii Stotskyi Jul 09 '12 at 21:18
  • This is getting ridiculous, people. Why 2 downvotes on this - without any explanation whatsoever? ) – raina77ow Jul 09 '12 at 21:28
1

Ok, by now most people have told you (rightfully so) that using three = is best practice. However, your example brings up one of the possible pitfalls when using type of value-of comparisons. Take this for example:

var date1 = new Date();
var date2 = new Date(date1.valueOf());

This means dat both date1 and date2 are of the same type (objects, the same object even: Date) and have exactly the same value. So logically:

console.log(date1 === date2);//logs FALSE

Why? Because JS object variables are references. What the above statement is actually doing is checking if two locations in memory (both are new instances) are the same. Not their contents is checked, but their mem address.
Logic therefore dictates that:

var date1 = new Date();
var date2 = date1;
console.log(date1 === date2);//True

Note: JS always copies the values of its variables, but in case of objects, those variables are references, so JS copies the mem address that is stored in date1 to date2.

Fair enough, the checking of two separate instances is an issue that occurs with double equal signs, too. Regardless of type, or value even: two mem addresses are never the same.

A simple fix many people used to apply, was to overwrite the JS object prototype's valueOf method. This still works, but causes problems with type and value checking (the object type is still playing part, then):

function SomeConstructor()
{
    this.foo = 'foobar';
    this.bar = function()
    {
        console.log('I am a messy constructor!');
        return this.foo;
    };
}
var inst = new SomeConstructor();
inst.valueOf = function()
{
    return 1;
}

console.log(inst == 1);//logs true
console.log(inst === 1);//logs FALSE

There are many ways to get around this, I've seen people JSON.stringify-ing two objects, and parsing them afterwards, people using for...in to check each property,... While all that needs to be done is storing the valueOf() return value in an extra variable. Job Done(?) What people actually need to do is write better code, but I'm tired and drifting WAY off topic where.... back to the question at hand:

What then, might one ask, is the reason to choose for the extra = sign. Well, I see consistency is mentioned above, and marginal speed gain.
But just as no-one seems to have mentioned this pitfall, there is nobody mentioning stability.

By that I mean that, when you're writing code, especially in a soft typed language, that you find yourself writing functions or methods that assume a certain number of arguments of a certain type.
The next step, generally while debugging, is that your functions start with lines like argument1 = parseInt(argument1); and argument1 = argument1 || 0; code like this can never be avoided all together, but should be kept to a minimum.

Speaking for myself, I tend to check what types of arguments are expected when calling a function, if I see that the function does type and value checking. If it doesn't I assume the function will parse whatever data it needs from whatever arguments I choose to pass to it.
Basically: the stricter your code looks the stricter it is likely to be used.

Elias Van Ootegem
  • 74,482
  • 9
  • 111
  • 149
  • Erm... you're comparing object and primitive here, so why you'd be surprised if `==` and `===` give different results? – raina77ow Jul 09 '12 at 21:34
  • It was an illustration of how the `.valueOf` method is called when using `==`, but not when using type and value checks. I might not have explained it all too clear, but Let it be known: I didn't expect the `inst === 1` to return true. `inst.valueOf() === 1` would log true since the return value is a primitive – Elias Van Ootegem Jul 09 '12 at 21:46
  • Why `valueOf` should be called when using _type_ check? Sorry, perhaps I do misunderstand you, but I really see nothing... strange in the code you've shown. – raina77ow Jul 09 '12 at 21:48
  • Well, in my last example: `inst == 1` evals to true, despite this, inst is an object, that has a method and a property, that is a string. `inst == 1` because `inst`'s valueOf method was redefined to return 1. When using double `=`, all object's `valueOf` methods are implicitly called, as part of the type juggling process. When adding an extra `=`, the `valueOf` method isn't called anymore. I merely wanted to point out that some code does depend on the `valueOf` to be called implicity. – Elias Van Ootegem Jul 09 '12 at 21:58
  • Again, why `valueOf` should be called in strict comparison? If you compare objects, you actually are comparing their references, calling `valueOf` is pointless there. And if you compare object with primitive, `===` will ALWAYS return `false` just because types are not matched. – raina77ow Jul 09 '12 at 22:03
  • comparing objects will always return false, too when using `==`, bc you are essentially comparing the memory addresses. Unless both variable names point to the same object in memory, the comparison will always return false. (0x9FFF0 === 0x9FFFF) is what you're checking for. when using double equal signs you're actually doing this (0x9FFF0.valueOf() == 0x9FFFF.valueOf()), just like ('1' == 1) is actually converted to (parseInt('1') == 1) Hence the first example `inst == 1` returned true: `inst.valueOf()` returns 1. Adding another `=` brakes this code, unless you call `.valueOf` explicitly – Elias Van Ootegem Jul 09 '12 at 22:11
-2

== - means check values of vars but dont check their types (e.g. "2" == 2 => return true).

=== - means check values and their types (e.g. "2" === 2 => return false, because the left argument is a string and second is a number, so vars doesnt the same)

EDIT: === in general the same as var1 == var2 && var1.contructor == var2.contructor.

Sergii Stotskyi
  • 5,134
  • 1
  • 22
  • 21
-2

Third equals compare even data types.

JavaScript typeof returns strings, only if tested variable is null doesn't return "null", but null.

If you are comparing typeof x with string, second equals return always the same such as third.

Arxeiss
  • 976
  • 16
  • 34