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:
- Why isn't "2" displayed when instantiating the variable/function
test
? - Why isn't "1" displayed when executing the variable/function
te开发者_运维问答st
?
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"
});
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();
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.
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)
Calling setup()
prints 1
and returns a reference to that anonymous function. Calling that prints 2
.
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.
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.
精彩评论