0

I'm trying to write a recursive function which returns the correct nested object within my model, based on an array of indexes.

My console log labelled 'inside function' actually shows the correct obj! Which is baffling me as all I do after that is return that obj, but the function appears to run again and return the parent.

JSFiddle

var model = [
    { name: 'Item 1' },
    {
        name: 'Item 2',
        sub: [
               { name: 'Item 2.1' },
               { name: 'Item 2.2' },
               { name: 'Item 2.3' }
        ]
    },
    { name: 'Item 3' },
    { name: 'Item 4' }
];

function getObj(collection, array) {
    var data = collection[array[0]];
    if(array.length > 1) {
        array.shift();
        arguments.callee(data.sub, array);
    }    
    console.log('inside function', data);
    return data;
}

var obj = getObj(model, [1, 2]); // expecting obj.name === 'Item 2.3'
console.log('result', obj); // obj.name === 'Item 2'
1
  • Note that "The 5th edition of ECMAScript (ES5) forbids use of arguments.callee() in strict mode. " - why not just use getObj(...) for better support? Commented Jun 19, 2015 at 15:14

2 Answers 2

1

When you're recursing

arguments.callee(data.sub, array);

you're not returning the result, instead you're ignoring the result and returning data from the initial call.

Try adding a return to that line so that the result of the recursive call is the result of the overall function.

Also be aware that arguments.callee won't work in strict mode.

Warning: The 5th edition of ECMAScript (ES5) forbids use of arguments.callee() in strict mode. Avoid using arguments.callee() by either giving function expressions a name or use a function declaration where a function must call itself.

To work in strict mode, you could do

return getObj(data.sub, array);
Sign up to request clarification or add additional context in comments.

5 Comments

Thanks, I thought arguments.callee seemed like best practice as no need to change multiple lines if you decide to change your function name, but good to know otherwise.
@daviestar A decent IDE will allow you to refactor all instances of the name at once, rather than manually updating them by hand.
@JamesThorpe I use PHPStorm.. how would I do that?
@daviestar No idea - never used it :) In my environment (Visual Studio with ReSharper), I just right click on the name to get a context menu with all sorts of options, one of which is Refactor->Rename. Could be anywhere in other IDEs though, if it even exists.
@daviestar, Yeah. arguments.callee will mean the same if the function name changes, but getObj will mean the same if you refactor part of the internals of your function into a separate function. I don't know which kind of change presents the greater hazard. JamesThorpe's suggestion to get the IDE to refactor for you is good one.
0

You should return in the recursion as well:

function getObj(collection, array) {

    var data = collection[array[0]];

    if(array.length > 1) {
        array.shift();
        return arguments.callee(data.sub, array);
    }    

    console.log('inside function', data);

    return data;
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.