tryGetValue in JavaScript


Recently, while working on a new JavaScript mockup I’ve noticed that JavaScript lacks a decent support for retrieving values of object properties. Constantly checking whether both object and property makes the code almost unreadable. But isn’t there a better to get the values of object properties and keep the JavaScript code to the minimum?

Let’s look at the following example:

var options = {
    filter: true,
    defaultText: "Lorem ipsum",
    multiList: false
};

The options variable is an object which provides a number of settings which will be used to instantiate another object. For the clarity of this example let’s assume that all of these properties are optional.

Whenever you want to retrieve a value of one of these properties you have to first check whether there are any options at all and then if the particular property has been set as well:

var Foo = function(opt) {
    // let's check whether the filter should be enabled
    var filter = false; // set default value
    if (typeof opt != "undefined" && typeof opt.filter != "undefined") {
        filter = opt.filter;
        // do something with the filter...
    }
}

var foo = new Foo(options);

Personally I find it a rather dirty way of retrieving properties plus imagine writing some larger piece of code: you would be repeating the code above over and over again. You could of course wrap the checks into an isDefined function, but still your code wouldn’t get much better.

The example I presented above is a typical scenario for a TryGetValue pattern. Typically a TryGetValue method/function is being called on a collection. The method/function takes (at least) two parameters: the name of the property of which the value you want to retrieve and an out parameter which will contain the value if succeeded. The try function/method returns a boolean true if the value has been successfully retrieved and a false if failed (property doesn’t exist, etc.).

Unfortunately for us JavaScript doesn’t support out parameters. While it has been extended with many great features over the last few years, it’s still far from what we know from C# for example. We could solve this issue using a workaround. You see we could simply modify the value of the value parameter. There is no way of telling JavaScript to pass a particular parameter by reference. It does it automatically. All primitive type variables are being passed by value and all objects by reference:

var alterA = function(value) {
    value = 2;
    return true;
};

var a = 1;
alterA(a);
alert(a); // i is still 1 because int is a primitve type

var alterB = function(obj) {
    obj.b = 2;
    return true;
}

var b = {
    b: 1
};
alterB(b);
alert(b.b); // b.b = 2 because b is an object

The above means that we must wrap all values into objects in order to get the desired result.

Having all the ingredients we could build the following tryGetValue function:

var Imtech = Imtech || {};
Imtech.isUndefined = function(obj) {
    return typeof obj == "undefined";
}

Imtech.isObject = function(obj) {
    return typeof obj == "object";
}

Imtech.tryGetValue = function(obj, property, result) {
    if (Imtech.isUndefined(result) || !Imtech.isObject(result)) {
        return false;
    }
    
    result.success = false;
    result.value = null;

    var fullProperty = "obj." + property;
    if (!Imtech.isUndefined(obj) && !Imtech.isUndefined(eval(fullProperty))) {
        result.success = true;
        result.value = eval(fullProperty);
    }

    return result.success;
}

aFirst of all we define two helper functions isUndefined and isObject which will help us check types of variables.

Inside tryGetValue

The first thing we have to do is to check whether the result parameter has been set and if it is an object. The tryGetValue in JavaScript will work only if the result parameter is an object.

Before we retrieve the value, we make a textual representation of the property which we will later evaluate using the JavaScript eval() function. Using the earlier defined check we control whether the property has been set and store its value if true.

You can call the above function as follows:

var filter = { value: false }; // provide default value
if (Imtech.tryGetValue(opt, "filter", filter) && filter.value) {
    // do something with the filter...
}

Doesn’t that look much better?

Wrap up

JavaScript evolved pretty well in the last couple of years. While the support in somewhat older browsers is poor, the modern browsers seem to agree on how JavaScript should work. If you’re both a developer and a web developer you may find JavaScript a really poor language. I won’t argue whether is right or wrong. Instead I can tell you that there are quite many things you could achieve with JavaScript nowadays. Applying concepts known from other programming languages simplifies not only writing but also managing JavaScript code.

Technorati Tags: JavaScript

Others found also helpful: