4

In javascript I have a lot of code like this.

if (ctrl && ctrl.main && ctrl.main.user) {
    SetTheme(ctrl.main.user.theme);
}

which is annoyingly long. In other, languages you can do simply

SetTheme(ctrl?.main?.user?.theme);

Is there any way to do that in javascript?

I tried,

function safeGet(a,b) { return a ? a[b] : null; }

and

SetTheme(safeGet(safeGet(safeGet(ctrl, 'main'), 'user'), 'theme'));

But that's not very readable.

John Henckel
  • 10,274
  • 3
  • 79
  • 79

2 Answers2

2

The correct short cut could be

if (((ctrl || {}).main || {}).user) { // ...

Or you could use an array as path, or a dot separated string as path and check aginst existence and return the value.

function getValue(object, path) {
    return path.split('.').reduce(function (o, k) {
        return (o || {})[k];
    }, object);
}

var ctrl = { main: { user: { theme: 42 } } };

console.log(getValue(ctrl, "main.user.theme"));
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
1

You could create a generic function to do this by passing it the string representing the path to the nested property you want:

  function getValue(object, prop, /*optional*/ valIfUndefined) {
            var propsArray = prop.split(".");
            while(propsArray.length > 0) {
                var currentProp = propsArray.shift();
                if (object.hasOwnProperty(currentProp)) {
                    object = object[currentProp];
                } else {
                    if (valIfUndefined) {
                        return valIfUndefined;
                    } else {
                        return undefined;
                    }
                }
            }

            return object;
        }

Then use this on any object like:

// This will return null if any object in the path doesn't exist
if (getValue(ctrl, 'main.user', null)) {
    // do something
}
mcgraphix
  • 2,723
  • 1
  • 11
  • 15