Safely referencing objects in javascript (understanding null and undefined)

Part 3

In Part 1, I discussed the difference between the null and undefined types in javascript. In Part 2, I talked about some techniques for properly checking to see if a variable, object, property or method is safe to access. In this 3rd and final part, I'm going to write a pair of functions that aid in safely referencing objects in javascript: the safeRef(..) function and the varExists(..) function.

The safeRef(..) function


function safeRef(obj, objType)
{
  if (typeof objType == 'string')
    { return (typeof obj == objType); }
  else if (typeof objType == 'object' && objType != null)
    { return (obj instanceof objType); }
  else
    { return (typeof obj != 'undefined' && obj != null); }
}

Utilizing this function is pretty straight-forward.


function Cat(name)
{
  this.name = name;
  this.eat = function() { alert(this.name + ' is eating!'); };
}

var c = new Cat('Felix');

if (safeRef(c.name))  // ensures that c.name is an existing property
  { alert('The cat\'s name is ' + c.name); }

if (safeRef(c.eat, 'function')  // ensures that c.eat exists and is a function
  { c.eat(); }

if (safeRef(c, Cat))            // ensures that c is of type Cat
  { alert('c is of type Cat'); }

This is a pretty good start, but suppose you have a custom object that may have another custom object as one of its properties, as in:


var a =
{
  b: { x: 5, y: 10 },
  c: { j: 15, k: 20 },
  d: { l: 0, m: 1 }
};

Trying to execute if (safeRef(a.b.whatever)) will result in an error. To solve this problem, I've created another function designed to work hand-in-hand with safeRef. It's called varExists(..).


function varExists(str)
{
  if (typeof str != 'string')
    { return false; }

  var props = str.split('.');
  var obj = window[props[0]];
  var i, propsLen = props.length;
  for (i = 1; i < propsLen; i++)
  {
    if (safeRef(obj[props<em>]))
      { obj = obj[props<em>]; }
    else
      { return false; }
  }

  return true;
}

The function, varExists(..) takes a string representation of the object/properties/methods you're trying to access and determines whether or not they can be accessed without causing a runtime error. Once you know that, you can use safeRef(..) to determine explicitely if the object/properties are of the type you're interested in.


var a =
{
  b: { x: 5, y: 10 },
  c: { j: 15, k: 20 },
  d: { l: 0, m: 1 }
};

if (varExists('a.b.whatever'))
  { alert(a.b.whatever); }

if (varExists('a.b.x'))
  { alert(a.b.x); }

// better yet…

if (varExists('a.b.x') &amp;&amp; safeRef(a.b.x, 'number'))
  { alert('a.b.x is a number: ' + a.b.x); }

Now, we have nice tools at our disposal. If we know for a fact that an object/property/method exists, we can simply use safeRef(..) to verify that it is safe to reference the object and that it is of the type we expect.

If we're not sure that a desired object/property/method exists, we can use varExists(..) to find out first, and then use safeRef(..) to make sure it's the proper type.

Final thoughts: As a final though, I'd like to say something that is probably going to surprise you. Whenever possible, I recommend avoiding to use of safeRef(..) and varExists(..). Yep, you read that right; I recommend avoiding them.

Why? Because I feel that most javascript programmers are far too lazy and careless when dealing with the variant types that are so intricate to the javascript language. I, personally, feel that we need to start treating javascript more like the strongly-typed languages we're used to (Java, C++, C#, etc…). In most languages, the compiler would never let you get away with trying to reference an undeclared variable.

In Javascript, you should never let yourself reference an undeclared variable.

A compiler would never let you mistakenly try to invoke a method of an object if that method doesn't exist.

In Javascript, you should know about the objects you're using. And you should know what properties and methods they support, and you shouldn't try to access anything that would be invalid.

Of course, this also requires quite a bit of care when writing your custom objects. But it's care that I feel is well worth the effort. For example, don't arbitrarily expose properties of your object if the improper modification of those properties could cause a problem. Instead, write explicit getters and setters and make sure that the passed-in values are valid.

But I digress… I could write another whole blog entry about this, but I'll spare you 😉

Hopefully you've learned something from this article. If nothing else, that javascript is more complicated than a lot of people realize. But hopefully you've also learned something valuable about what the null and undefined types mean to the javascript interpreter and about how to ensure safe referencing of variables, objects, properties and methods.

Comments/suggestions welcome.

7 thoughts on “Safely referencing objects in javascript (understanding null and undefined)”

  1. Brilliant tutorial, mate! I'm finally working with javascript again for the first time in ten years since hacking around as a teenager; it's the accurate, well-written posts like this one that are filling in so many gaps for me.

  2. Nice post.

    One remark to your statements "[..] frequently using the typeof operator exclusively to check for the existence of a variable [..] is probably a sign of bad program design" and "[indicates] that your objects [..] are too tightly coupled":

    I don't agree here, because I suggest using this check as good practice especially in loosley coupled objects to verify pre-conditions. For instance in setter methods with variant parameters this makes very much sense.

  3. Till,

    Granted, the concept has its proper place, and the scenario you point to makes sense. My point is just that if you don't know what properties/methods exist on an object, and you constantly find yourself "guessing" or "testing the waters" by using typeof to determine if a method or property exists, you might want to rethink the design a tad. In my experience, when programming like that is overused, it leads to unwieldy and difficult to maintain code.

  4. Hello!
    Very Interesting post! Thank you for such interesting resource!
    PS: Sorry for my bad english, I'v just started to learn this language 😉
    See you!
    Your, Raiul Baztepo

  5. Hello ! 😉
    My name is Piter Kokoniz. Just want to tell, that your posts are really interesting
    And want to ask you: what was the reasson for you to start this blog?
    Sorry for my bad english:)
    Tnx!
    Piter Kokoniz, from Latvia

  6. @Pieter:

    Thanks for your comments. I started the blog just as a way to keep a programming reference for myself and the things I've learned, and also as a way to share what I've learned with others.

  7. Dude, nice explanation.
    Just a minor typo bug –
    —————-
    A better solution is to verify the existence of the variable and then verify that it it isn't null.

    if (typeof someVar != 'undefined' && someVar != 'null')
    { // someVar exists and isn't null }
    At this point you can be sure that someVar is safe to access
    —————

    The NULL in if condition should not be within quotes. In rest of the page it's what it should be, so certainly it was a typo only.
    Cheers!

Leave a Reply

Your email address will not be published. Required fields are marked *