views:

452

answers:

5

So I have been through most of the questions here. Also quite a few articles good and bad.

One thing I am looking for some additional clarification on is how undefined and un declared variables are treated.

Take the code below.

var a;

if(a == null) // True - Due to Type Coercion

if(a == 'null') // False

if(a === null) // False

if(a === 'null') // False

if(a == undefined) // True

if(a === undefined) // True

if(a == 'undefined') // False

if(a === 'undefined') // False

if(a) // False - A is undefined

alert(typeof(a)) // undefined

All of the above I understand. But things get weird when you look at an undeclared variable. Note I am specifically omitting a "var b;".

 alert(typeof(b)) // undefined

 if(typeof(b) == 'undefined') // True

 if(typeof(b) === 'undefined') // True - This tells me the function typeof is returning a string value

 if(typeof(b) == 'null') // False

 if(typeof(b) === 'null') // False

 if(typeof(b) == null) // False

 if(typeof(b) === null) // False

 if(b) // Runtime Error - B is undefined

Any other operation then typeof(b) results in a runtime error. Still I can understand the logic behind the way the laguage is evaluating expressions.

So now I look at a non existent property of a and am really confused.

if(a.c) // Runtime Error - c is null or not an object
alert(typeof(a.c)) // Runtime Error - undefined is null or not an object

I would think that c in this case would be treated like b in the previous example but its not. You have to actually initialize a to something then you can get it to behave as b does. And stop it from throwing runtime errors.

Why is this the case? Is there some special handling of the undefined type or is the typeof function doing something recursively to evaluate the sub property that is throwing the runtime error?

  1. I guess the practical question here is if I am checking a nested object c in a.c I can immediately assume c is undefined if a is undefined?

  2. And what is the best way then if I wanted to check some extremely nested object to see if it was set like x in MyObject.Something.Something.Something.x ? I have to navigate through the structure element by element making sure each one exists before going to the next one down in the chain?

+2  A: 

I can immediately assume c is undefined if a is undefined?

Yes.

I have to navigate through the structure element by element making sure each one exists before going to the next one down in the chanin?

Yes.

jldupont
typeof null === 'object' // true
NV
a is undefined, not null
NV
@NV: maybe you could point this out to the author? i.e. "if(a.c) // Runtime Error - c is null or not an object" *a* being *undefined* and not *null*.
jldupont
A: 

Normally you won't come across the need test an extremely (more than three levels) nested object where any of the parents could be undefined. So when you do need to test, I would write it something like this:

if( typeof(a) != 'undefined' && a.c ) {
   // Do something won't run because a is undefined
}

var a = {};

if( typeof(a) != 'undefined' && a.c ) {
   // Do something won't run because though a is defined,
   // a.c is undefined. This expression tests to see if a.c evaluates
   // to true, but won't throw an error even if it is 
   // undefined.
}

If a.c could at any time contain 0 or false but you still needed the test to pass, then use the full typeof test:

var a = {};
a.c = false;

if( typeof(a) != 'undefined' && typeof(a.c) != 'undefined' ) {
   // Do something will run because though both a and a.c are defined.
}
Doug Neiner
A: 

The reason why

alert(typeof(a.c))

results in a runtime error and

alert(typeof(b))

does not is that in the first example you are trying access a property on an undefined object, which causes a runtime error before the result can be fed into typeof()

Peter
A: 

JavaScript is odd in that the value undefined (also typeof a === "undefined") is what variables have until they are given a value. null is a distinct value which is different from undefined. Since the type system in JavaScript is loose there is an implicit type coercion that happens when comparing and testing values of variables.

If a variable is undeclared then you cannot reference it without errors but you can test it with the typeof operator (and its result will be the string "undefined"). A variable which has been declared but not assigned is able to be referenced but still contains the value undefined. You can always reference undefined properties of objects and if they have not been assigned then they will have the value undefined.

See this answer too as I went into more detail about JavaScript type coercion and different values which are often useful to consider empty:

http://stackoverflow.com/questions/1275960/#1276252

  1. When testing nested objects, if the parent is undefined (or null) then it has no children so no further testing is needed.

  2. To safely test a heavily nested object you will need to test the topmost parent using typeof but you can test any children for actual values (see the testing for empty answer). This is because the top level may not have been declared, but you can always reference undefined properties of objects.

McKAMEY
A: 

Don't forget that undefined is global variable (!), and you (or someone else) can assign it a value, so your example can be wrong here:

if(a == undefined) // True

if(a === undefined) // True

If you really need undefined, then you can get your own "copy" of it

var local_undefined;
MBO