Q:

Build path to deep object tree in JavaScript

I have this code:
const getObject = (container, id, callback) => {
    _.each(container, (item) => {
        if (item.id === id) callback(item);
        if (item.files) getObject(item.files, id, callback);
    });
}

that will get me the object inside an object such as this:
const structure = {
    id: 1,
    name: "Struct",
    files: [
        {
            id: 2,
            type: "folder",
            name: "assets",
            files: [
                {
                    id: 3,
                    type: "folder",
                    name: "important",
                    files: [
                        {
                            id: 4,
                            type: "folder",
                            name: "modules",
                            files: [
                                {
                                    id: 5,
                                    type: "folder",
                                    name: "foo",
                                    files: [
                                        {
                                            type: "file",
                                            name: "foo.js"
                                        }

                                    ]
                                },
                                {
                                    id: 6,
                                    type: "folder",
                                    name: "bar",
                                    files: [
                                        {
                                            type: "file",
                                            name: "bar.js"
                                        }

                                    ]
                                }
                            ]
                        }

                    ]
                }
            ]
        }
    ]
}

Example:
getObject(structure.files, 6, (target) => {
    console.log(target)
})  // returns { "id": 6, "type": "folder", "name": "items", "files": [ { "type": "file", "name": "bar.json" } ] }

My problem is that I need to get the "path" back to the initial element (structure.files). What is the best way to go around this? 
For example in this situation, it would return [1,2,3,4,6].

A:

You could use the classic function and this argument for the path in the callback for Array#some. Return full path when the target is found.

var structure = { id: 1, name: "Struct", files: [{ id: 2, type: "folder", name: "assets", files: [{ id: 3, type: "folder", name: "important", files: [{ id: 4, type: "folder", name: "modules", files: [{ id: 5, type: "folder", name: "foo", files: [{ type: "file", name: "foo.js" }] }, { id: 6, type: "folder", name: "bar", files: [{ type: "file", name: "bar.js" }] }] }] }] }] },
    path;

[structure].some(function iter(a) {
    if (a.id === 6) {
        path = this.concat(a.id);
        return true;
    }
    return Array.isArray(a.files) && a.files.some(iter, this.concat(a.id));
}, []);

console.log(path);

ES6 version with closure for the path collecting variable p.

var structure = { id: 1, name: "Struct", files: [{ id: 2, type: "folder", name: "assets", files: [{ id: 3, type: "folder", name: "important", files: [{ id: 4, type: "folder", name: "modules", files: [{ id: 5, type: "folder", name: "foo", files: [{ type: "file", name: "foo.js" }] }, { id: 6, type: "folder", name: "bar", files: [{ type: "file", name: "bar.js" }] }] }] }] }] },
    path,
    iter = p => a  => {
        if (a.id === 6) {
            path = p.concat(a.id);
            return true;
        }
        return Array.isArray(a.files) && a.files.some(iter(p.concat(a.id)))
    };

[structure].some(iter([]));

console.log(path);

