1

We have a large hierarchical object (worst possible legacy design) in javascript. The problem I am facing is that there is a list of null checks I need to perform whenever I want to access an element deep within the object structure.

Say I have a bank object which contains a list of customers and I want to get the address of the first customer,

if(bank != null ||
bank.customerlist != null ||
bank.customerlist.customer[0] != null ||
bank.customerlist.customer[0].address != null )
{

transactionAddress = bank.customerlist.customer[0].address;
}

This is just a small example,I cannot believe so many null checks are required just to access a single value.

It there a better way around this?

DntFrgtDSemiCln
  • 1,259
  • 2
  • 16
  • 35
  • 1
    encapsulate it in `try { ... } catch (e) { ... }` – phylax Apr 15 '14 at 16:10
  • It seems this question was a duplicate. My answer here is almost the same as [@kennebec's](http://stackoverflow.com/a/2631521/1529630) in the other thread; I didn't copy him, tough. – Oriol Feb 23 '15 at 21:53

2 Answers2

2

You can use try catch block:

try {
    var transactionAddress = bank.customerlist.customer[0].address;
} catch(e) {
    // handle the error here
}
katranci
  • 2,551
  • 19
  • 24
1

You could create your own accesser function:

function access(obj, path) {
    var arr = path.split('/');
    while(obj && arr.length)
        obj = obj[arr.shift()];
    return obj;
}

And use it like this:

var bank = {
    customerlist: {customer: [{address: 'foo'}]}
}
access(bank, 'customerlist/customer/0/address'); // 'foo'
access(bank, 'bar/foo/foobar');                  // undefined (no error)

Also consider using...

function access(obj, path) {
    var arr = path.split('/');
    while(obj!=null && arr.length)
        obj = obj[arr.shift()];
    return obj;
}

...if you want to use access with non-objects, e.g. you want access('', 'length') to return 0


Explaining,

function access(obj, path) {
    var arr = path.split('/');
    while (
        obj /* To avoid `null` and `undefined`. Also consider `obj != null` */
        && /* Logical AND */
        arr.length /* Check that `arr` still has elements */
    ) {
        obj = obj[arr.shift()]; /* `arr.shift()` extracts the first
                                   element is `arr` */
    }
    return obj;
}
Oriol
  • 274,082
  • 63
  • 437
  • 513
  • This looks like a good option, im kinda new to javascript, can you tell me what exactly is being done in this while condition : while(obj && void 0 !== (prop = arr.shift())) ? – DntFrgtDSemiCln Apr 15 '14 at 17:42
  • @DntFrgtDSemiCln It checks that `obj` is truly (to avoid `null` and `undefined`), it extracts `arr`'s first element to `prop`, and checks that `prop` is not `undefined` (I use `void 0` because `undefined` could have been altered). – Oriol Apr 15 '14 at 17:47
  • Thank you very much for the explanation! @Oriol , also do you think the try catch blocks would help too? – DntFrgtDSemiCln Apr 15 '14 at 18:08
  • @DntFrgtDSemiCln I have simplified a bit my code (since I don't know if it's faster to attempt a `shift()` or to check `length`, I use the simplest one) – Oriol Apr 15 '14 at 18:14
  • @DntFrgtDSemiCln Yes, the `try catch` works too, but I find it ugly :) Also note that if an error is thrown in a `try catch`, there is a small performance penalty. No idea if it's worse than the penalty of calling a function, though. – Oriol Apr 15 '14 at 18:18