mko
mko

Reputation: 22044

Confusing about parameter passing in Javascript

<html>
    <head>
    </head>
    <body onload=>  
        <button></button>
        <script>
        function give_show(value) {
            return function() {
                console.log(value);
            }
        }

        var button_element =document.getElementsByTagName('button')[0];
        button_element.addEventListener('load',give_show('bong!'),false)
        </script>
    </body>
</html>

The above code works. in console I got:

bong!

However, if I change this part:

function give_show(value) {
    return function() {
        console.log(value);
    }

to

function give_show(value) {
    return function(value) {
        console.log(value);
    }

I got something like

mouse.event

What's causing that to happen?

FYI: I use Safari console to get the result.

Upvotes: 2

Views: 143

Answers (4)

Jones
Jones

Reputation: 1500

I change load for click on listners and add console.log before return internal function:

<html>
    <head>
    </head>
    <body>  
        <button></button>
        <script>
            function give_show(value) {
                console.log(value);

                return function(value) {
                    console.log(value);
                }               
            }

            var button_element =document.getElementsByTagName('button')[0];
            button_element.addEventListener('click',give_show("bong!"),false);
        </script>
    </body>
</html>

confusion is when give_show is passed to addEventListner. In example give_show run before you click in button and Bong! is write on console. The addEventListner only recognizes function:

function(value) {
    console.log(value);
}               

and event(click) pass to value the position of clicked by mouse. This is same to make this:

button_element.addEventListener('click',function(value) {
                                            console.log(value);
                                        },
                                 false);

If you suppress value parameter value used is from passed to give_show function.

Upvotes: 0

Herms
Herms

Reputation: 38798

Nested functions have access to everything defined in the scope in which they are created. So:

function give_show(value){
  return function(){ console.log(value); }
}

when you reference value in the nested function the variable defined in give_show is in scope and is used.

However, when you do this:

function give_show(value){
  return function(value){ console.log(value); }
}

you are returning a function that takes an argument value, so that variable name hides the one defined by give_show.


To make what's happening in the second case more obvious, this code does exactly the same thing, without hiding the value variable from the outer scope:

function give_show(value){
  return function(event){ console.log(event); }
}

The console.log method is using the argument passed to your returned function, and is completely ignoring the value passed to give_show. This is why you're getting 'mouse.event' and not 'bong!' in your second case - event handlers are passed the event as their argument.

Upvotes: 2

user1106925
user1106925

Reputation:

You can visualize it this way...

function give_show(value) { // <-- 1. You passed 'bong!'

    return function(value) { // <-- 2. Browser passes the Event object <--------+
//                                                                              |
        console.log(value); // <-- 3. Will use the nearest "value" it finds ----+
   };
}

So the returned function is used as the event handler. When an event occurs, the browser pass an Event object to that function. Since you named the parameter value, console.log will use that.


If you didn't give the name value to the handler function, the next value would be the one defined in your give_show function...

function give_show(value) { // <-- 1. You passed 'bong!' <----------------------+
//                                                                              |
    return function(foo) {   // <-- 2. Browser passes the Event object          |
//                                                                              |
        console.log(value); // <-- 3. Will use the nearest "value" it finds ----+
   };
}

Upvotes: 1

driangle
driangle

Reputation: 11779

This happens because at the time that you're calling console.log(value); the value variable is referring to the parameter of the most inner function. This parameter overrides the value of the parameter you passed into give_show because it has the same name. When that function is called as a result of a click event, the browser will pass the actual click event object as the first parameter into that inner function, which is why you see mouse.event when you do console.log.

Upvotes: 1

Related Questions