Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

JavaScript

Lost....again...function within a function?

What I'm confused about is the how the second function references the first function?

Secondly, what is the order that the rendering engine is doing within this code??

function say(something){ // I get this

  console.log(something);


function exec(func, arg){ // I don't get this, how does this link the two functions together?

  func(arg); //what does this do??????????? I don't see any properties or methods present.

}


exec(say, 'Hi, there.');

//how does the 'say' know enough to use the second parameter as an argument within itself? Can someone make equivalent code logic to this while using different key words.
I understand a function can work in a function, I just don't understand how the syntax is telling the Javascript interpreter to do that.

3 Answers

Jennifer Nordell
seal-mask
STAFF
.a{fill-rule:evenodd;}techdegree
Jennifer Nordell
Treehouse Teacher

Wow, you've gotten some nice answers here. I'm almost a bit shy about posting mine, but I also made an example although it includes even an extra function. Remember also, that functions (or references to functions) can be passed around in your code just like any other variable. In fact, you can set a variable to reference a function, which is what I did in the second part of this. Take a look and see if it makes sense.

// Say hello to someone
 function greetPerson(personsName) {
     console.log("Hi there, " + personsName);
 } 

 // That person says hi back.
 var sayHiBack = function(personsName) {
     console.log("Nice to meet you, " + personsName);
 } 

 function runThis(functionToRun, personsName) {
     //the thing passed into functionToRun is a reference to the function
     // the personsName will be the argument passed into the appropriate function
     functionToRun(personsName);
 }

 runThis(greetPerson, "Greg Schudel");
 runThis(sayHiBack, "Jennifer");

Our last 2 lines here are our function calls. The first one calls the runThis function and passes in the function name, and the person's name. I'm going to kick this off by saying hi to you. So our code goes up and finds the reference to runThis. Inside of runThis we accept the name of the function we want to run and the name of the person. In the first case, we passed in greetPerson, so it then goes up to greetPerson which takes a name of a person. This was passed in as an argument from the functionToRun as personsName. The function then performs the console.log statement with the name of the person sent in.

In the last line, it's much the same. We start by calling the runThis function and then passing in the reference to the function we want run. This time, you're going to say hi back to me so we send in my name. As you'll notice in this case, the sayHiBack is a variable holding a reference to a function. Inside this, We passed my name to the runThis which then passes it along to sayHiBack.

You've gotten some brilliant answers here, but if you have any questions or comments, feel free to ask! :sparkles:

It's a bit clearer...couple questions

 function greetPerson(personsName) {
     console.log("Hi there, " + personsName);
 } 

 var sayHiBack = function(personsName) {
     console.log("Nice to meet you, " + personsName);
 } 


// so this gets run first from the callbacks below?
// does order matter with this?
 function runThis(functionToRun, personsName) {

     functionToRun(personsName);// isn't this kinda like a infinite loop since it's just referencing itself?
 }

 runThis(greetPerson, "Greg Schudel");
 runThis(sayHiBack, "Jennifer"); // if you removed the sayHiBack variable and then it became an anonymous function, how would you call it? Could you still call or do you have to name it?
Jennifer Nordell
seal-mask
.a{fill-rule:evenodd;}techdegree
Jennifer Nordell
Treehouse Teacher

First, I think you're confusing a callback with a normal function call. The last two lines are function calls. They call a function named runThis. That function has two parameters. Now you could try to send in runThis(2, "Jennifer");, but it will fail because the line inside demands that it be a function. There is no way here to send in an anonymous function that I know of. We're specifically telling runThis which function we want to run. Thus, it must be named.

So ok, we send in greetPerson. Remember, parameters are essentially local variables only defined during the life cycle of that function. What you have now is something akin to functionToRun = greetPerson and personsName = "Greg Schudel". That line functionToRun(personsName); is now equivalent to greetPerson("Greg Schudel");. The function does not reference itself although that can happen and is known as recursion which is a much more advanced topic. The function itself is called runThis. If it had referened itself, we'd have a line starting a call to runThis.

Finally, the function definitions may be in any order. However, the calls to the functions must come after they are defined. If you put the last two lines at the top, or anywhere between the function definitions it will not work.. But you can put runThis at the top and totally reorder the definitions without it having any effect.

Welcome to javascript and the weird things that make javascript awesome. In javascript, functions are first class citizens which means you can pass a function as an argument to another function. Just like you can pass any variable as an argument. That is exactly happening in your example.

function say(something){ //Here we just have a regular function

  console.log(something);
}


function exec(func, arg){ //Here we have a more special function - it takes a function as an argument. How do I know that?

  func(arg); //I know that because func(arg) is telling me that func must be a function as it is executed here

}

exec(say, 'Hi, there.'); //now here you are executing your exec function. and passing it a function reference. So imagine the inside of your function now looking like:

exec(say, 'Hi, there.') {
         say('Hi, there');   //and you know this function from the very top. just a very boring regular function
}

This is a very common pattern in javascript and is what makes up callback functions. I am sure you have seen syntax like this:

button.addEventListener('click',function() {
       //do something in here
      //the function you pass is a callback function
});

Having this knowledge you can utilize your own functions that take callbacks

function someFunctionWithaCallback(firstName, lastName, callback) {
        var fullName = firstName + " " + lastName;
        callback(fullName);       

}

//Now let's use that callback
someFunctionWithaCallback('Joe', 'Doe', function(theFullName) {
              console.log(theFullName); //Joe Doe
});

Understand that concept and you will find javascript a lot more powerful

function someFunctionWithaCallback(firstName, lastName, callback) {// understand this
        var fullName = firstName + " " + lastName;
        callback(fullName);       // but this doesn't make the fullName a function within a function, does it? 

}

and are you creating an instance or a constructor function here?

I am not creating an instance function. Its just a regular function.

function someFunctionWithaCallback(firstName, lastName, callback) {// understand this
        var fullName = firstName + " " + lastName;
        callback(fullName);       // fullName is just the variable from above that I pass into the callback function as a parameter
}

//When i now want to execute this regular function by passing in an anonymous function as my callback,
//I know that the parameter to the callback will be the fullName that is created in the inside of the someFunctionWithaCallback
someFunctionWithaCallback(firstName,lastName, function(fullName) {
             //do stuff here with the fullName
});

You just need to know that you can treat a function just like a regular variable in javascript. Pass them around and even pass them into functions as parameters like we are doing here

Jonathan Grieve
MOD
Jonathan Grieve
Treehouse Moderator 91,254 Points

I think what's happening is the exec function is taking 2 arguments. It's kind of like the glue that links the 2 functions together. 1 parameter, is the name of a function, which is the previously defined say function. So that becomes the first value when you call the exec function - that value is the same of the say function.

Then the second argument is the argument for the message. It's where the something keyword comes in.

It wouldn't work if you passed in a direct value to the console.log method, but as it's a reference to a value, you can call it directly with exec.