8

Can this code

if (typeof foo != "undefined" && foo !== null) { }  

be safely refactored into this code?

if (foo != null) { }

Is it the exact same thing? (And if not, how is it different?)

Šime Vidas
  • 182,163
  • 62
  • 281
  • 385

3 Answers3

11

Not really. You'll get thrown a ReferenceError exception in your second example if foo has not been declared.

On the other hand, you can safely check for undefined non-declared variables with the typeof operator.

Daniel Vassallo
  • 337,827
  • 72
  • 505
  • 443
  • @Daniel I don't understand. If I have `var foo;` and then run the second snippet, no error will be thrown (at least not in Chrome). – Šime Vidas Dec 05 '10 at 18:45
  • @Sime: Try `if (aNewFoo != null) { }` without declaring `var aNewFoo;` before. Then try `if (typeof aNewFoo != 'undefined') { }`, again without declaring the variable... That is the difference. – Daniel Vassallo Dec 05 '10 at 18:46
  • @Daniel Aha, so if `foo` is not declared, then an error will be thrown, and if it is declared but just happen to hold the undefined value, then no error will be thrown. Correct? – Šime Vidas Dec 05 '10 at 18:48
  • @Sime: Yes, exactly. Therefore `typeof x === 'undefined'` can check for variables which have not been declared or have been set to `undefined`. That is the main difference between your two examples. – Daniel Vassallo Dec 05 '10 at 18:51
  • @Daniel It seems that the problem with the error being thrown does not occur if we test a property (like `window.foo`) instead of just a variable (`foo`). In this case the longer form `(typeof window.foo != "undefined" && window.foo !== null)` is equivalent to the shorter form `(window.foo != null)`, right? – Šime Vidas Dec 05 '10 at 23:17
  • @Šime: Yes, true. `undefined` and `null` are both falsy, and the `!=` operator will do type coercion. Therefore that would work out the same... But you can use `window.propertyName` only for variables in the global namespace. If you have a local variable within a function, that becomes more complicated. – Daniel Vassallo Dec 05 '10 at 23:37
2

A simple experiment will answer this question:

if( foo != null ) {
   alert('foo not null');
}

the above example yields a javascript error in many browsers: "ReferenceError: Can't find variable: foo". This is because we've used a variable that has not been previously declared as an argument or var in current scope.

the typeof operator, on the other hand, makes an explicit accommodation for variables that haven't been defined -- it returns 'undefined', so:

if( typeof foo != 'undefined') {
    alert('foo is not defined');
}

works as expected.

So the answer is "no" -- they are not the same thing -- though in some javascript environments they may behave the same way, in other environments your second form will produce errors when foo is not defined.

Lee
  • 13,462
  • 1
  • 32
  • 45
2

Variables can actually hold the value undefined, which is the default value if a variable has never been assigned to. So foo != null will work if your variable is declared using var or given a value through assignment, but if it isn't, you will get a ReferenceError. Therefore, the two snippets are not equivalent.

If you can be sure that foo is declared, this is safe and easier to understand than your original second snippet, assuming that nowhere in the code something like undefined = 42 exists:

if(foo !== undefined && foo !== null) { }
PleaseStand
  • 31,641
  • 6
  • 68
  • 95
  • So, if `foo` has been declared (like in `var foo;`), then my two snippets are equivalent. But if `foo` has not been declared the two snippets are not the same, because the second snippet throws an error. Correct? – Šime Vidas Dec 05 '10 at 18:52
  • @Šime Vidas: As far as I can tell, yes. I still think the original snippet is better because it is more clear what it does. To quote from Douglas Crockford's JavaScript: The Good Parts: "The evil twins do the right thing when the operands are of the same type, but if they are of different types, they attempt to coerce the values. the rules by which they do that are complicated and unmemorable." – PleaseStand Dec 05 '10 at 18:58
  • Yes, the first snippet is the way to go. I thought that I can simplify that check (since null == undefined in JavaScript), but it turns out I can't. – Šime Vidas Dec 05 '10 at 19:03