JavaScript self-invoking function

2019-08-05 18:12发布

问题:

I got this example from page 79 of a book called Object Oriented JavaScript by Stoyan Stefanov. Not really knowing what to do, the first time I ran this program (by hitting enter) it returned 'undefined'. After that, following the author's instructions, I called it a(); and got the alert 'Worky worky'

My questions are

a) Did I do the first step correctly? i.e. am I supposed to run a self-invoking program by merely hitting "enter/return"?

b) if I was correct to just hit "enter/return" to run the program, why did it give a result of "undefined." This program, says the author, refuns a reference (on its first run-through) to the function actualWork() ? if it returns a reference, why is that considered undefined? Is it important somehow?

Note that I tried to enter the code in jsfiddle.net and then hit run and nothing happened, but that I got "undefined" when I ran it the first time in the console and then the alert afterwards when I did a();

var a = function() {
    function someSetup(){
        var setup = 'done';
    }
    function actualWork(){
        alert('Worky-worky');
    }
    someSetup();
    return actualWork;
}();

回答1:

a) depending on how your interpreter works, yes, simply running the script (by pressing return) defines function a();

b) it gave "undefined" because the program itself doesn't return anything, but the function a(); does. the code you quoted above represents a function a(); which, when invoked, should do the following:

  1. define 2 other (temporary) functions
  2. run one of them (someSetup)
  3. return the other one.

so i would use the program by:

  1. running to define a();
  2. calling var x=a();
  3. (optional) checking if setup=='done'
  4. calling x(); (which was returned by a()) should show the alert.

EDIT sorry, i didn't see the }(); at the end, so it's not 100% correct. the (); at the end is - as Jon and Tomasz both said - short form for "take the function's return value as a new function and run it immediately".



回答2:

This code is equivalent to:

var f = function() {
    function someSetup(){
        var setup = 'done';
    }
    function actualWork(){
        alert('Worky-worky');
    }
    someSetup();
    return actualWork;
};

var a = f();

So: You are creating variable f and assigning a function to it. Then You assign the result of invoking f() to a, which happens to be a function as well (this is done implicitly in the original code). And at the very end you can run a(), which runs the the function returned by f().



回答3:

"Self-invoking" means that this code has an immediate effect immediately after it is executed by the compiler, even though all the code is inside a function. This happens because the function is immediately invoked (those () in the last line).

This is also what would have happened if you wrote just

function someSetup(){
    var setup = 'done';
}
function actualWork(){
    alert('Worky-worky');
}
someSetup();
return actualWork;

The difference here is that the "self-invoking program" (which is a bad description for what it is, IMHO) allows you to do this without making the names someSetup and actualWork visible to the calling code -- this is generally desirable.

With that explained, let's answer your questions:

  1. The code snippet does not return anything itself (even if it assigns to a something that is returned by a function); therefore your JS IDE reports that its return value is undefined.
  2. The reference to function actualWork is returned fine (it's the value assigned to a); you saw that yourself when you successfully called it with a().


回答4:

undefinded is returned from statements var a = ... that is OK. Reference is returned by the right side of assigment.



回答5:

The anonumous function is invoked immediately and returns a reference to the function actualWork within it. So a contains this reference and can be invoked by itself. So a(); should give you the alert.