22

[Bounty Edit]

I'm looking for a good explanation when you should set/use null or undefined and where you need to check for it. Basically what are common practices for these two and is really possible to treat them separately in generic maintainable codee?

When can I safely check for === null, safely check for === undefined and when do I need to check for both with == null

When should you use the keyword undefined and when should one use the keyword null

I have various checks in the format of

if (someObj == null) or if (someObj != null) which check for both null and undefined. I would like to change all these to either === undefined or === null but I'm not sure how to guarantee that it will only ever be one of the two but not both.

Where should you use checks for null and where should you use checks for undefined

A concrete example:

var List = []; // ordered list contains data at odd indexes.

var getObject = function(id) {
    for (var i = 0; i < List.length; i++) {
        if (List[i] == null) continue;
        if (id === List[i].getId()) {
            return List[i];
        }
    }
    return null;
}

var deleteObject = function(id) {
    var index = getIndex(id) // pretty obvouis function
    // List[index] = null; // should I set it to null?
    delete List[index]; // should I set it to undefined?
}

This is just one example of where I can use both null or undefined and I don't know which is correct.

Are there any cases where you must check for both null and undefined because you have no choice?

Raynos
  • 166,823
  • 56
  • 351
  • 396
  • For my own edification, why do you care? I mean, why not just test with `== undefined` unless you **know** you don't want to match `null`? – Hemlock Jan 20 '11 at 14:54
  • Firstly JSLint complains. It's neater to use `===`. I would like to be able to treat `undefined` and `null` seperately. I think there are clear cases where you should use one or the other but I don't understand them. Almost everyone doesn't bother understanding the minor differences between the two and just uses `== null` or `== undefined`. Javascript does seem to have both without any distinction. – Raynos Jan 20 '11 at 15:00
  • 1
    Use the *bang operator* (`!`): `if (!someObj)` – alexia Jan 20 '11 at 15:09
  • 1
    @raynos: do you have a link on that subject? I always use `!` and would appreciate learning if I've been doing something stupid. – fearofawhackplanet Jan 20 '11 at 15:49
  • @raynos great article thanks for the link – fearofawhackplanet Jan 20 '11 at 16:29
  • http://typeofnan.blogspot.com/2011/01/typeof-is-fast.html I made a research about the performance, probably helpful too. – jAndy Jan 31 '11 at 18:41
  • those suggesting `!` need to consider an id of 0 in the List example above – Dagg Nabbit Jan 20 '12 at 17:42

9 Answers9

11

Functions implicitly return undefined. Undefined keys in arrays are undefined. Undefined attributes in objects are undefined.

function foo () {

};

var bar = [];
var baz = {};

//foo() === undefined && bar[100] === undefined && baz.something === undefined

document.getElementById returns null if no elements are found.

var el = document.getElementById("foo");

// el === null || el instanceof HTMLElement

You should never have to check for undefined or null (unless you're aggregating data from both a source that may return null, and a source which may return undefined).

I recommend you avoid null; use undefined.

Matt
  • 74,352
  • 26
  • 153
  • 180
  • thank you, i will try to check for `undefined` and keep an eye on methods like `document.getElementById` that return `null`. On that matter what is the actual purpose and good usage of `null` it seems to only be there because it's a common keyword in most languages. Undefined seems to be more applicable for almost all it's uses. – Raynos Jan 20 '11 at 15:05
  • @Raymos: See http://stackoverflow.com/questions/461966/why-is-there-a-null-value-in-javascript/463608#463608 – Matt Jan 20 '11 at 15:18
5

Some DOM methods return null. All properties of an object that have not been set return undefined when you attempt to access them, including properties of an Array. A function with no return statement implicitly returns undefined.

I would suggest making sure you know exactly what values are possible for the variable or property you're testing and testing for these values explicitly and with confidence. For testing null, use foo === null. For testing for undefined, I would recommend using typeof foo == "undefined" in most situations, because undefined (unlike null) is not a reserved word and is instead a simple property of the global object that may be altered, and also for other reasons I wrote about recently here: variable === undefined vs. typeof variable === "undefined"

Community
  • 1
  • 1
Tim Down
  • 318,141
  • 75
  • 454
  • 536
  • I have confidence my co-workers don't declare global variables called `undefined`. The typeof variables is good for checking undeclared variables rather then non-existant properties/values – Raynos Jan 20 '11 at 15:34
  • 1
    @Raynos: It's also good for host objects. Also, it's possible to reassign `undefined` inadvertently if you're someone whose habit is to put the constant on the left hand side of a comparison and you accidentally miss off an `=` sign. For example: `if (undefined = foo) {...}` will throw no error but sliently redefines `undefined`. – Tim Down Jan 20 '11 at 16:18
  • @Raynos I spent 4 hours last weekend tracking down a bug caused by a library that redefined undefined by accident. The code was something like window[obj.id] = obj, where obj.id was not necessarily defined. – Patrick McElhaney Jan 29 '11 at 18:55
  • @PatrickMcElhaney that could have been avoided by namespacing. Besides its easier to just defined a local `undefined` if you need it. – Raynos Jan 29 '11 at 19:28
  • @Raynos True. The undefined check was in another library, jQuery UI -- which is why I asked the question Tim referenced. :-) – Patrick McElhaney Jan 29 '11 at 19:32
3

The difference between null and undefined is that null is itself a value and has to be assigned. It's not the default. A brand new variable with no value assigned to it is undefined.

var x;
// value undefined - NOT null.
x = null;
// value null - NOT undefined.
Surreal Dreams
  • 26,055
  • 3
  • 46
  • 61
  • Which is the ironic thing since `null` means literally the lack of a value. I understand the difference and the rationale, but it's still a little bit weird that they are distinct operators when they are the same concept (mathematically at least)... – ircmaxell Jan 20 '11 at 14:52
  • Are you sure that there aren't values that are `null` without being set to null? (This includes common practices like where 3rd party code will set things to null, i.e. jQuery or where the DOM sets values to null). If that's the case I can check for `undefined` everywhere apart from where I specifically set things to `null` – Raynos Jan 20 '11 at 14:52
  • @Raynos – If *you* don't explicitly set a variable to `null`, it won't be `null`, but you can never be sure a 3rd party script won't do this. That said, this is one of the reasons why you should use your own namespace within an anonymous self-invoking function. To make things worse: please remember that accessing an undeclared variable (using `var`) will throw an exception, in that case you'll have to use the `typeof` operator. – Marcel Korpel Jan 20 '11 at 15:00
  • most of the time, when jquery (specifically a selector $('...')) returns that it did not find anything, it returns an empty array. neither `null` nor `undefined`. – helloandre Jan 20 '11 at 15:03
  • @MarcelKorpel I'm aware that accessing an undeclared variable does throw an exception. Almost all my checks for `undefined` are on `Array[i]` or `Object[key]` – Raynos Jan 20 '11 at 15:06
  • @contagious: Yep, in this case, you can use `$('#myObj').length` for checking. – alexia Jan 20 '11 at 17:55
2

I think it's interesting to note that, when Windows was first written, it didn't do a lot of checks for invalid/NULL pointers. Afterall, no programmer would be dumb enough to pass NULL where a valid string was needed. And testing for NULL just makes the code larger and slower.

The result was that many UAEs were due to errors in client programs, but all the heat went to Microsoft. Since then, Microsoft has changed Windows to pretty much check every argument for NULL.

I think the lesson is that, unless you are really sure an argument will always be valid, it's probably worth verifying that it is. Of course, Windows is used by a lot of programmers while your function may only be used by you. So that certainly factors in regarding how likely an invalid argument is.

In languages like C and C++, you can use ASSERTs and I use them ALL the time when using these languages. These are statements that verify certain conditions that you never expect to happen. During debugging, you can test that, in fact, they never do. Then when you do a release build these statements are not included in the compiled code. In some ways, this seems like the best of both worlds to me.

Jonathan Wood
  • 65,341
  • 71
  • 269
  • 466
1

If you call a function with no explicit return then it implicitly returns undefined. So if I have a function that needs to say that it did its task and there is nothing result, e.g. a XMLHTTPRequest that returned nothing when you normally expect that there would be something (like a database call), then I would explicitly return null.

CyberFonic
  • 3,957
  • 1
  • 21
  • 21
0

Undefined is different from null when using !== but not when using the weaker != because JavaScript does some implicit casting in this case.

The main difference between null and undefined is that undefined can also mean something which has not been assigned to.

                            undefined   false
(SomeObject.foo)            false        false
(SomeObject.foo != null)    false        true
(SomeObject.foo !== null)   true         true
(SomeObject.foo != false)   true         false
(SomeObject.foo !== false)  true         false

This is taken from this weblog

Marcel Korpel
  • 21,536
  • 6
  • 60
  • 80
Jón Trausti Arason
  • 4,548
  • 1
  • 39
  • 46
  • 2
    I know what null and undefined are. I want to know where to use them and how to avoid checks for both. – Raynos Jan 20 '11 at 14:49
0

The problem is that you claim to see the difference, but you don't. Take your example. It should really be:

var List = []; // ordered list contains data at odd indexes.
var getObject = function(id) {
    for (var i = 1; i < List.length; i+=2) {
        if (id === List[i].getId()) {
            return List[i];
        }
    }
    // returns undefined by default
}

Your algorithm is flawed because you check even indexes (even though you know there's nothing there), and you also misuse null as a return value.

These kind of functions should really return undefined because it means: there's no such data

And there you are in the heart of the problem. If you don't fully understand null and undefined and may use them wrongly sometimes, how can you be so sure that others will use it correctly? You can't.

Then there are Host objects with their nasty behavior, if you ask me, you better off checking for both. It doesn't hurt, in fact, it saves you some headaches dealing with third party code, or the aformentioned non-native objects.

Except for these two cases, in your own code, you can do what @bobince said:

Keep undefined as a special value for signalling when other languages might throw an exception instead.

gblazex
  • 49,155
  • 12
  • 98
  • 91
  • That particular code would fail because I remove objects from the `List`. Then `List[i].getId()` will through a reference error. Also it's a matter of where it's appropiate to return `null` internally in your code/ – Raynos Jan 29 '11 at 13:22
0

When to set/use them...

Note that a method without a return statement returns undefined, you shouldn't force this as an expected response, if you use it in a method that should always return a value, then it should represent an error state internally.

Use null for an intentional or non-match response.


As for how/when to check...

undefined, null, 0, an empty string, NaN and false will be FALSE via coercion. These are known as "falsy" values... everything else is true.

Your best bet is coercion then testing for valid exception values...


var something; //undefined

something = !!something; //something coerced into a boolean

//true if false, null, NaN or undefined
function isFalsish(value) {
  return (!value && value !== "" && value !== 0);
}

//get number or default
function getNumber(val, defaultVal) {
  defaultVal = isFalsish(defaultVal) ? 0 : defaultVal;
  return (isFalsish(val) || isNaN(val)) ? defaultVal : +val;
}

Numeric testing is the real bugger, since true, false and null can be coerced into a number, and 0 coerces to false.

Tracker1
  • 19,103
  • 12
  • 80
  • 106
  • I know all about "falsy" values. I'm interested in avoiding `o == null` which checks for both `null` & `undefined` – Raynos Jan 30 '11 at 14:21
0

I would treat them as 2 completely different values, and check for the one you know might occur.

If you're checking to see if something has been given a value yet, check against undefined.

If you're checking to see if the value is 'nothing,' check against 'null'

A slightly contrived example:

Say you have a series of ajax requests, and you're morally opposed to using callbacks so you have a timeout running that checks for their completion.

Your check would look something like this:

if (result !== undefined){
    //The ajax requests have completed
    doOnCompleteStuff();
    if (result !== null){
        //There is actually data to process
        doSomething(result);
    }
}

tldr; They are two different values, undefined means no value has been given, null means a value has been given, but the value is 'nothing'.

david
  • 17,925
  • 4
  • 43
  • 57
  • Are you saying that if the `result` is `null` I should do on complete stuff? – Raynos Feb 02 '11 at 02:27
  • Yes, because you know the call has completed because result is no longer `undefined` – david Feb 02 '11 at 02:29
  • For example, you're pulling a customer's address out of a database, initially the address will be undefined, until the call completes. If the database doesn't have the address, then after the request completes the result will be null. – david Feb 02 '11 at 02:30