Edward Tanguay
Edward Tanguay

Reputation: 193352

Why does a Javascript function act differently upon instantiation than execution?

I'm coming from C#/PHP and trying to get my head around Javascript's idea that functions are variables/objects and have quasi constructors, etc.

Can anyone explain why the following code functions as it does, namely:

  1. Why isn't "2" displayed when instantiating the variable/function test?
  2. Why isn't "1" displayed when executing the variable/function test?

code:

var setup = function () {
    console.log(1);
    return function() {
        console.log(2);
    };
};

var test = setup(); // 1
test(); // 2
test(); // 2
test(); // 2

added:

Thanks @thejh @Justin so the function is returning a completely different function that has nothing to do with the first (I was thinking of the second function as a kind of constructor of the first), if I comment it out, it's clearer:

$(document).ready(function() {

    var setup = function () {
        console.log(1);
//        return function() {
//            console.log(2);
//        };
    };

    var test = setup(); // 1
    test(); // "test is not a function"
    test(); // "test is not a function"
    test(); // "test is not a function"

});

Upvotes: 2

Views: 344

Answers (6)

Alin P.
Alin P.

Reputation: 44346

Imagine instead of

var setup = function () {
    console.log(1);
    return function() {
        console.log(2);
    }
}

this equivalent OOP syntax

var setup = new Function("\
    console.log(1);\
    return new Function(\"\
        console.log(2);\
    \");\
");
var test = setup(); // 1
test(); // 2
test(); // 2
test(); // 2

I think things should be more familiar to you now.

Upvotes: 1

Baptiste Pernet
Baptiste Pernet

Reputation: 3384

Hello when you do setup() you execute this two lines :

console.log(1);
function() { console.log(2); }
  • the first line log "1"
  • the second line doesn't log any thing, because the function is not called, it only create an object (and this object is a function).

when you do test() you actually call the function you've created and so you log "2"

JS is a functional language, you have to see functions like first citizen object.

Upvotes: 1

thejh
thejh

Reputation: 45578

Calling setup() prints 1 and returns a reference to that anonymous function. Calling that prints 2.

Upvotes: 1

brad
brad

Reputation: 32355

In your first assignment of test to setup(), you're executing the whole function, so console.log(1) runs, then returns a new function.

Now, you're assigning the return value of that first function to be the next function that runs console.log(2), so now test references that returned function.

Your subsequent calls just run that function which runs console.log(2)

Upvotes: 1

Justin Niessner
Justin Niessner

Reputation: 245449

You're only calling setup() the first time. Once it is called, the new function it returns is assigned to test. From there on, you're calling that new function:

// calls setup which logs 1 and returns a new function.
// setup also returns a new function and assigns that new function to test.
var test = setup(); 

// test now is the equivalent of var test = function(){ console.log(2); };

// call the new function that setup returned which logs 2
test();

// and again
test();

// and again
test();

Upvotes: 5

Nick Craver
Nick Craver

Reputation: 630549

Because you're returning a different function from what gets called when creating it (the one in the return, one you're not calling on the first line)...that's what gets executed on the other calls. For example this would give you 1 then 2:

var test = setup()(); // 1, 2

You can test it here.

Upvotes: 5

Related Questions