Traversing javascript/json based on a dot-separated lookup string I have an object of arbitrary depth, and a string (or array) containing the keys which have to be traversed to get to the value.

As far as I know, there's no method to get to the value directly:

var object = { 
    user: {name: 'bob'}, 
    'user.name': 'error'
};

object['user.name']; // contains 'error'


And the usual:

object['user']['name'];


is not possible without doing some very dirty eval stuff, because you do not know how far you will need to traverse through the object beforehand.

So I think this is only solvable using a recursive function:

var object = {
    company: {
        users: [
            {name:'alice',age:'20'},
            {name:'bob',age:'22'},
            {name:'eve',age:'30'},
        ]
    }
};

lookup = function recurse(array,object) {
    var next = (array.length) ? object[array.shift()] : object;
    return (next instanceof Object &amp;&amp; next[array[0]]) ? recurse(array,next) : next;
}

var search = 'company.users.0.name';
lookup(search.split('.'), object);


I think this works well enough, but would love some feedback.

Efficiency is important here, could I rewrite the function to shave of a few milliseconds somewhere? Are there any pitfalls, bugs or exceptional cases to consider?
The very first problem I see is:

next instanceof Object


That's because almost everything, if not everything, in JS is an instance of Object. Go try new Date() instanceof Object and even that is true. That said, you can do it this way but you must assume that it's just a structure containing objects and arrays. Otherwise, you'll have to check for every possible kind of object out there. This means dates, regexes, DOM objects, functions etc.

Another way to do this is to create a function dynamically. I've seen frameworks do this, especially when it deals with templates containing JS expressions. Instead of lugging around a full-blown expression parser, they let the browser's parser do it. The advantage of this method over eval is that you only evaluate the expression once. You can then cache the generated function in some object for reuse. You can even have it return undefined or null if the entire subtree is missing instead of getting an error.

function createResolver(keypath){
  return new Function('root', `
    try { return root.${keypath}; }
    catch(e){ return undefined; }
 `);
}

// Return foo.bar.baz
var obj1 = { foo: { bar: { baz: 'bam!!!' }}};
var resolver1 = createResolver('foo.bar.baz');
var value1 = resolver1(obj1);

// Even when the subtree is missing, you can safely call it
var obj2 = { foo: {}};
var resolver2 = createResolver('foo.bar.baz');
var value2 = resolver2(obj2);

// Normally, this throws an error:
var value3 = obj2.foo.bar.baz