6

Could somebody explain to me the difference between if(obj.x == undefined) and if(typeof obj.x == 'undefined')

In some context the first one works fine, but in other I need to use the second way.

Questions

1 - What is the difference between the two condition?

2 - Is there a best practice?

David Laberge
  • 15,435
  • 14
  • 53
  • 83
  • see http://stackoverflow.com/questions/776950/javascript-undefined-undefined – Marek Sebera Aug 29 '11 at 14:59
  • Often it's good enough to just check the _truthiness_ of the value: `if (obj.x)`. – Matt Ball Aug 29 '11 at 15:01
  • `undefined` is a variable, not a constant, and can be assigned a value. Because of this, one school of thought says the second path is safer, since you cannot be sure of the value of `undefined`. There is another school of thought that says those who redefine undefined deserve exactly what they get. – Chris Nielsen Aug 29 '11 at 15:07
  • If you want to know if a property exists on an object, do this `if ( 'x' in obj )` or this `if ( obj.hasOwnProperty( 'x' ) )`. (Use the second one, if you don't want to look up the prototype chain. – Šime Vidas Aug 29 '11 at 15:10
  • @Chris Nielson - as of 1.8.5 `undefined` is non-writable – jondavidjohn Aug 29 '11 at 15:15
  • @David Note that one can explicitly assign the `undefined` value to a property. Therefore, when a property returns the value `undefined` it can mean two things: (1) the object doesn't have such a property, (2) the object does have such a property and it's values is `undefined`. So, if you need to check whether or not a property exists in an object, don't compare it to `undefined`, but instead use one of the two methods I provided in my comment above. – Šime Vidas Aug 29 '11 at 15:37

6 Answers6

10

The best practice is to not just check the truthiness but the strict equality

example

if (obj.x === undefined) {}

this use to be an issue because undefined (a global property) use to be writable, as of 1.8.5 is is non-writable, providing you with a secure comparison in ES5 spec environments.

per MDN

jondavidjohn
  • 61,812
  • 21
  • 118
  • 158
  • A secure comparison? In which environment? Afaik, you can assign to the `undefined` variable in all modern browsers... – Šime Vidas Aug 29 '11 at 15:23
  • 1
    It's still not reliable. Even in ES5, `undefined` can be used as a variable name within a function: `(function() { var undefined = "foo"; alert(undefined); })()` – Tim Down Aug 29 '11 at 15:37
  • Then why would the MDN choose this as the primary example of how to see if a variable is `undefined`? – jondavidjohn Aug 29 '11 at 15:39
  • @Šime: @jondavidjohn is right about the global `undefined` property being read-only in current browsers. – Tim Down Aug 29 '11 at 15:39
  • @jondavidjohn: MDN is not infallible. – Tim Down Aug 29 '11 at 15:39
  • @Tim It doesn't appear to be read-only: http://jsfiddle.net/mCYuq/1/ (tested in Chrome, Opera and IE8) – Šime Vidas Aug 29 '11 at 15:45
  • I'm not asserting they are, I'm simply trusting the architect of the language to not propagate bad practices of their own product. – jondavidjohn Aug 29 '11 at 15:48
  • MDN is not written by Brendan Eich. It's also publicly editable. More to the point, unquestioningly trusting any resource other than the language's spec is a mistake. @Šime: I've responded about browser specifics in the comments to my answer. – Tim Down Aug 29 '11 at 15:52
  • @jon You say in your answer that `x === undefined` is a secure comparison, but it isn't. You can still write to `undefined` in Chrome and Opera, so as for now `x === undefined` is **not** secure, ergo, it's a potential security threat (as tiny as it is, it still is one). – Šime Vidas Aug 29 '11 at 15:58
1

The two would usually be equivalent if you replaced the equality operator == with the strict equality operator ===. So obj.x === undefined and typeof obj.x == "undefined" are usually equivalent.

However, in pre-ECMAScript 5 environments (which still acount for the majority of web requests, in general), undefined is a writable property of the global object, meaning that undefined may be used as variable name or the global property may be assigned a different value. ECMAScript 5 makes the global property read-only, but even then, undefined may still be used as variable name within a function, meaning that the typeof check is always safer.

One further point in favour of typeof is that it may be used to check for a variable that may not have been declared whereas a direct comparison will throw a ReferenceError if the variable has not been declared. For example:

typeof foo == "undefined" // true
foo === undefined // ReferenceError

However, this is an unusual and not generally helpful thing to be doing.

Tim Down
  • 318,141
  • 75
  • 454
  • 536
  • In what browsers is `undefined` (the global variable) not writable? – Šime Vidas Aug 29 '11 at 15:33
  • 1
    @Šime: Try it. I've tried it on my machine in Firefox 6, Chrome 13, Safari 5.1 and Opera 11.50. Safari and Firefox do not allow assignment to the `undefined` global object property, Chrome and Opera do. However, that's not very relevant: the point is that a compliant ES5 environment will not allow it, and such environments do exist. – Tim Down Aug 29 '11 at 15:50
  • And I just happened to only have Chrome and Opera on my machine `:)`. – Šime Vidas Aug 29 '11 at 15:54
1

The two are not equivalent tests because of the quite convoluted handling of special values by javascript. In the specific

undefined == null

is true, but typeof undefined is "undefined" while typeof null is "object".

The rules for those special values are quite complex and IMO illogical, so I think there's no "general rule". What you may find are common forms, for example

var value = obj.x || default_value;

that can be used if you're sure that obj will never be undefined or null (because in that case an exception would be thrown) and assuming that 0, NaN or an empty string should be considered as if no value was provided (because they're all "logically false" values). An empty array or an empty javascript object instead are considered "logically true".

Why is it that way? Why does (null).x throw an exception when null according to typeof is apparently an object and searching for a non-existent field in an object normally returns undefined instead?

I've no idea.

I never tried to find a logic in all those strange rules. I'm not actually even 100% sure there's one.

My suggestion is just to study and experiment with them.

6502
  • 112,025
  • 15
  • 165
  • 265
  • If you're unsure of why this admittedly unintuitive behaviour happens, check the ECMAScript specification. Your observations follow directly from well-defined rules you'll find there. – Tim Down Aug 29 '11 at 15:57
  • @Tim Down: I've actually tried to check the specs but I personally found that document close to impossible to read. I prefer experimenting with those side cases because anyway it wouldn't be that helpful writing programs that in theory should run but that in practice don't (unless you target is not writing software that runs but just being able to find someone to blame instead). – 6502 Aug 29 '11 at 17:44
0

The main difference of these two condition is typeof

The typeof operator is used to get the data type (returns a string) of its operand. The operand can be either a literal or a data structure such as a variable, a function, or an object. The operator returns the data type.

if (typeof obj.x === 'undefined') {
    txt = "x is undefined";
  } else {
    txt = "x is defined";
  }
Pankaj Chauhan
  • 1,623
  • 14
  • 12
0

second is easier and faster than first. First requires additional setup, definition of undefined and check wheter obj contains x as a property or method. second makes the check whether obj.x has been whenever defined and assigned

PS.: undefined will be evaluated to null so obj.x == undefined is equivalent to obj.x == null

i100
  • 4,529
  • 1
  • 22
  • 20
0

the best way to test for conditionality isusing obj.x this checks for both null-ability and undefined .

Thus

if(!obj.x) 
{
  alert(obj.x);
}
else   
{
  alert("obj.x is null or undefined");  //obj.x is null or undefined or any false value which is what you want. like obj.x is false or 0
}
Baz1nga
  • 15,485
  • 3
  • 35
  • 61
  • This is not correct. The else-branch will be executed if `obj.x` is any falsy value, not just null or undefined. – Šime Vidas Aug 29 '11 at 15:15