23

I'm relatively new to coding in JavaScript, and I've came across a problem. I like to nest functions to keep things orderly, but how would I exit from a parent function from inside a child function?

example:

function foo1() {
   function foo2() {
      //return foo1() and foo2()?
   }
   foo2();
}
4
  • 1
    Without more example code it would be hard to envision a reason why anyone would want to try this. This example code does not even compile. Commented Jan 8, 2014 at 15:10
  • I'm making a game... I have all my games code in "play()" and inside play i want the function "die()" to stop "play()" Commented Jan 8, 2014 at 15:11
  • "I'm making a game... I have all my games code in "play()" and inside play i want the function "die()" to stop "play()"" If your game involves interacting with the outside world in anyway, it seems really unlikely that play will still be running when you decide that something should "die", because of the asynchronous way most JavaScript environments (including browsers) handle user-initiated events. Commented Jan 8, 2014 at 15:16
  • What environment is this game run in? Commented Jan 8, 2014 at 15:18

5 Answers 5

15

See update under the fold

You can't. You can only return from the child function, and then return from the parent function.

I should note that in your example, nothing ever calls foo2 (As of your edit, something does). Let's look at a more real example (and one that comes up a lot): Let's say we want know if an array contains an entry matching some criterion. A first stab might be:

function doesArrayContainEntry(someArray) {
    someArray.forEach(function(entry) {
        if (entryMatchesCondition(entry)) {
            return true; // Yes it does           <-- This is wrong
        }
    });
    return false; // No it doesn't
}

You can't directly do that. Instead, you have to return from your anonymous iterator function in a way to stop the forEach loop. Since forEach doesn't offer a way to do that, you use some, which does:

function doesArrayContainEntry(someArray) {
    return someArray.some(function(entry) {
        if (entryMatchesCondition(entry)) {
            return true; // Yes it does
        }
    });
}

some returns true (and stops looping) if any call to the iterator function returns true; it returns false if no call to the iterator returned true.

Again, that's just one common example.


You've referred to setInterval below, which tells me that you're almost certainly doing this in a browser environment.

If so, your play function almost certainly has already returned by the time you want to do what you're talking about, assuming the game has any interaction with the user other than alert and confirm. This is because of the asynchronous nature of the environment.

For example:

function play() {
    var health = 100;

    function handleEvent() {
        // Handle the event, impacting health
        if (health < 0 {
            // Here's where you probably wanted to call die()
        }
    }

    hookUpSomeEvent(handleEvent);
}

The thing is, that play will run and return almost immediately. Then the browser waits for the event you hooked up to occur, and if it does, it triggers the code in handleEvent. But play has long-since returned.

Sign up to request clarification or add additional context in comments.

5 Comments

Do you have any recommendations of something I could do?
Well, it depends on what we understand by "return". Raising an exception will propagate.
Return a bool (true/false), depending on if the function is successful or not, then have the parent function determine what to do next.
Wouldn't I have to have a setInterval or something to continually check?
@user3025700: If you're doing anything like that, your play will have already returned.
2

Make a note whether the parent function should also return.

function foo1() {
    bool shouldReturn = false;

    function foo2() {
        shouldReturn = true;    // put some logic here to tell if foo1() should also return 
        return;
    }

    if (shouldReturn) {
        return;
    } else {
        // continue
    }
}

Comments

1

It only says that you can't return the parent function in the child function, but we can do a callback and make it happen.

function foo1(cb = () => null) {
   function foo2() {
      cb();
   }

   foo2();
}

foo1(() => {
    // do something
});

Comments

0

We can use Promises for this:

const fun1 = async () => {
    const shouldReturn = await new Promise((resolve, reject) => {
        // in-game logic...
        resolve(true)
    })

    if(shouldReturn) return;
}

if you wanna return from the parent function, then just resolve with true

Comments

-2

Based on your comment, something like this might work as a main game loop.

function play() {

var stillPlaying = true;
    while(stillPlaying) {
     ... play game ...
      stillPlaying = false; // set this when some condition has determined you are done
    }
}

1 Comment

Couldn't that generate a loop that crashes the browser?

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.