pierrespring.com

geek, punk, pussy …

JavaScript values null and undefined

In JavaScript everything is an Object. Everything but null and undefined.

The first few times I read this, it didn’t really strike me. Simply because I had never seen or used null in my own JavaScript code. But having worked with the Google Maps API recently, I came across null and wondered what the difference between the two could be.

To be completely honest, I saw how one of my workmates used it. I shook my head, looked at him and told him the following thing in an annoyingly patronizing manner: “You know what, null isn’t part of the JavaScript language. In JavaScript we have undefined, which is the same than null in PHP” He just pointed me to some code in the Google Maps API and smiled. I was baffled by both, my ignorance and the existence of null. What could this null be. And how would it relate to undefined?

Some investigation showed what most people would have derived from the names of both these language constructs.

null is a value. Or rather a non-value. It is the value you can assign to a variable or an object property, when you don’t know what else to assign. It is often used in order to intialize an object property.

var child = {
  name: null,
  baptize: function (name) {
    this.name = name;
  }
}

In some cultures, like in Finland, this actually makes sense. Finnish children do not get a name before they are baptized. But this is an other story.

Now that you have a child object, you might want to know if the child has a name. As I mentioned in the beginning, null is not an object, so you’d expect to be able to test for something like typeof child.name != 'null'. Unfortunately, typeof null returns 'object'. This is an error in the specification of JavaScript. And it is not likely to change. As a result we end up with the following getName() function:

var child = {
  name: null,
  baptize: function (name) {
    this.name = name;
  },
  getName: function () {
    if (typeof this.name == 'object') {
      return this.name || ‘Not named yet’;
    }
    return this.name;
  }
}
child.getName(); // -> 'Not named yet.'
child.baptize('Pierre');
child.getName(); // -> 'Pierre'
child.baptize({first: 'Frank', middle: 'Alvar'});
child.getName(); // -> {first: 'Frank', middle: 'Alvar'}

So, even though null is not an object, typeof null returns 'object'. But we can take advantage of the fact that every JavaScript object is typecasted to true and null is typecasted to false.

Now we know what null is. But what is undefined? undefined is even less than null. It is the default value for variables and parameters and the value of missing members in objects:

// default value for variables
var lessThanNull;
typeof lessThanNull; // -> 'undefined'

// default value for parameters
var getType = function (p) {
  return typeof p;
}
getType() // -> 'undefined'

// value of missing members in objects
var empty_object = {};
typeof empty_object.notInitialized; // ->'undefined'

var colors = ['red', 'green', 'orange'];
delete colors[1];
typeof colors[1]; // ->'undefined'

That’s it.

Just to compare it to PHP: Every time you get undefined somewhere in your JavaScript code, PHP would return null and trigger a Notice. I personally think that JavaScript has chosen the more elegant solution.

Tags:

5 Responses to “JavaScript values null and undefined”

  1. Yoan says:

    I usually find the “in” operator way nicer to tests the presence of something, or the hasOwnProperty if you’re picky. Once again, you must know what you’re doing at any time: https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Operators/Special_Operators/in_Operator#Using_in_with_deleted_or_undefined_properties

    Food for thought regarding the last example above: https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Operators/Special_Operators/delete_Operator#Deleting_array_elements

  2. Michael says:

    I don’t know if I follow your conclusion. In my opinion accessing a non existing property should very much throw an error, to prevent long debugging sessions when there’s some evil typo in your code. At least that happens to me far more often than that I have a need for the behavior you described.

    By the way, to make the second example (with null) less verbose, you can also use the fact that null evaluates to false and use this shortcut:

    return this.name || 'Not named yet';
  3. Pierre Spring says:

    @yoan: I had never heared of the in operator before. Yet, for the purpse of this article, which is to understand the difference between null and undefined I think the examples are better off without it.

    I read the link about deleting array elements. And my head kind of doesn’t get why someone would do the following:

    var children = ['Lou', 'Frank', Lillith];
    children[2] = undefined; // makes no sense

    children = ['Lou', 'Frank', Lillith];
    // is slow, yet the only solution not to
    // fuck with the length property and having
    // vanilla for loops working as expected. no?
    children.splice(2,1);

    @michael: Thanks for pointing out the shortcut. I’ll edit the post right away! Now, what I meant to say about PHP is that I dislike the fact that it sets an undefined variable to null. Not the fact that it triggers a notice. I like the fact that PHP triggers a notice, yet most people working with PHP do not display them ;)

  4. Chris D says:

    Smile… :-)
    Way to go. Nice to see you working on this blog. Keep up the good work!

  5. Yoan says:

    Applying `delete` on an array seems very counter-intuitive to me. I’d expect it to behave like (the awesome) splice but it doesn’t.

    js> var a = [1,2,3]
    js> delete a[1]
    true
    js> a.hasOwnProperty(2)
    false
    js> a.length
    3

    it’s not the same as doing it manually though (even if you say that it makes no sense)

    js> a[2] = undefined
    js> a.hasOwnProperty(2)
    true
    js> for(var i in a){ print(i) }
    0
    2

    It’s very very confusing, I think. I’m feeling all PHPish at this point :-)

    @michael, @shvi just go with the ternary operator: return typeof this.name === "object" ? this.name : "No named yet"