javascriptfunctionstatements

JavaScript validates variable types different when they are undefined and null


I saw this question in a test, where the variable myObj was not declared, and requsted to choose the correct answer based on the following if statements.

function myFunction() {
  if(typeof myObj !== "undefined" && myObj !== null) {
    a = 1
  }
}

result: "undefined" 

Created the functions to run these statements and test output.

 function myFunction() {
   if(myObj !== null && typeof myObj !== "undefined") {
    a = 1
   }
 }

 result: Uncaught ReferenceError: myObj is not defined

my questions is if an variable is not defined, isn't that the same as "undefined", if I want to test for a "undefined" value, I can just use "null" to check if its undefined by (e.g myObj === null), so why is the fist function returns undefined and the second returns myObj is not defined?


Solution

  • There are a couple of things going on:

    1. Value checks are different from type checks.

      If you try to read the value of an identifier that doesn't exist, you get an error. So myObj === null causes an error if myObj doesn't exist (the identifier has never been declared or otherwise created).

      But using typeof on an identifier that doesn't exist results in "undefined", without an error. So typeof myObj is "undefined" when myObj doesn't exist. You can see this in the specification where it does:

      2(a) If IsUnresolvableReference(val) is true, return "undefined".

    2. The && operator short-circuits.

      && evaluates its first operand and, if that value is falsy,¹ takes the falsy value as its result, doing nothing with the second operand. If the first operand's value is truthy, though, && evaluates the second operand and takes that value as its result.

    Because of those two things, if(typeof myObj !== "undefined" && myObj !== null) { works without error because it does typeof myObj !== "undefined" first and, since that value is false when myObj doesn't exist, the result of the && operation is true and the second operand is never evaluated. But if(myObj !== null && typeof myObj !== "undefined") { does myObj !== null first, trying to use the value of an identifier that doesn't exist, which causes the error.

    my questions is if an variable is not defined, isn't that the same as "undefined"

    Not in the general case, no. typeof is special. Just about anything else you do with an identifier that doesn't exist will raise an error. (Okay, there's one other thing: in loose mode, if you assign to an identifier that doesn't exist, it creates a global. This is what I call The Horror of Implicit Globals and is one of the many reasons to use strict mode, where it's the error it always should have been.)


    ¹ "truthy" and "falsy" are terms we use in JavaScript to refer to vlaues that coerce to true and values that coerce to false when used as conditions. There is a fixed set of falsy values: 0, "", NaN, null, undefined, and of course, false (also document.all in browsers; weird but true). All other values are truthy.