Recursive, depth first search
The main issue with your function is that it can't correctly search for null or undefined.

findDeep(['foo', 'bar', 'bam'], i =&gt; i === null); // (1)
findDeep(['foo', 'bar', null], i =&gt; i === null);  // (2)
findDeep(['foo', , 'bam'], i =&gt; i === undefined); // (3)


(1) and (2) both return null and (3) returns undefined even though there is no such value.


I would rather make the function return an object, similar to ES2015
generators.
Separate index argument is excessive if you are
ok with mutating keys.
I would rename test to
pred for
"predicate"
and item to value to take advantage of ES2015's shorthand properties.
let is the new var.


function findDeep(dict, pred, keys = Object.keys(dict)) {
    if (keys.length === 0) {
        return { match: false };
    }

    let value = dict[keys.pop()];

    if (pred(value)) {
        return { match: true, value };
    }

    if (value !== null &amp;&amp; typeof item === 'object') {
        let result = findDeep(value, pred);

        if (result.match) {
            return result;
        }
    }

    return findDeep(dict, pred, keys);
}


Last, please keep the coding style consistent: note the space (or no space) after if and the indentation.