Self-executing anonymous functions and closures

2019-08-31 01:26发布

问题:

information

I am trying to build a site where I can include certain files and append to my global variable with different methods that will just add easily to the object. Meaning I only need to include the file and this page will now have access to everything in the hutber object.

core hutber.js

var hutber = {};

(function ($) {
    "use strict"; //For good development standards :)

    hutber.init = function(){

    };
    hutber.init();
})(jQuery);

extra bits hutber.form.js

(function ($) {
    "use strict"; //For good development standards :)

    hutber.form = {

    }

});

problem

I am aware that the hutber will not have access to hutber.form as it within a closure. So without taking these out of selfexecuting functions how can I get hutber to have access to hutber.form? Or is this just the complete wrong way to approach this?

回答1:

No it will have access to hutber.form since hutber is global, but the problem is timing.

If the init() runs before the hutber.form function is executed, it will not be there. The init can not run to all of the "add-ons" are loaded.

A side note: your second one will not run since it has no (jQuery);.

(function ($) {
    "use strict"; //For good development standards :)

    hutber.form = {

    }

});  <-- missing  (jQuery); so it is not going to do anything

Run a little demo to see what happens.

var myObj = {};

(function(){

    myObj.init = function(){
        alert("init");
        try{ //will fail since bar has not loaded yet
        myObj.bar();
        } catch(e){ alert("failed calling bar"); }
    };
    //call init before bar is loaded
    myObj.init();
})();


(function(){

    myObj.bar = function(){
        alert("bar");
    };
})();

//call init after bar has been loaded
myObj.init();

jsFiddle of above code

When you run this, you will see that the init will fail the first time it is called since bar is not loaded. The second time it will work since the method is added. So if the init depends on the loaded "modules" it needs to know when they are loaded in order to call the init method.



回答2:

I think you want this:

<script src="hutber.js"></script>
<script src="hutber.form.js"></script>
<script> hutber.init(); </script>


回答3:

Seeing as how you defined hutber as a global variable the "form" property will certainly be accessible within any immediately invoked function expression.



回答4:

You might be looking at this the wrong way.

Not to say that immediately-invoked functions are the wrong way to build functionality...

What I am saying, however, is that you've got a globally-available object, which you're referencing directly from within your function...

After you assign hutber.form = {};, everything in whole world of the global scope has full access to hutber.form, because hutber is globally-accessible.

It really wouldn't be any different than if you went like:

//form.js
hutber = hutber || {};
hutber.form = { /* ... */ };

In terms of public access to hutber.form.

The closure covers the things you DON'T return and the things that you DON'T assign to objects/arrays/vars in an outer-scope.

So if you had var mySecretIdentity = "Jerry O'Connell"; inside of the closure, then only the methods inside of hutber.form could access mySecretItentity...

...but again, you could accomplish the same by doing something like:

// form.js
hutber = hutber || {};
hutber.form = (function () {
    var mySecretIdentity = "Jerry O'Connell";

    return {
        submit : function () {},
        clear  : function () {},
        validate : function () {}
    };
}());

And now anything private can only be directly-accessed by the functions which were written inside of the closure.

So again, it comes down to: "What problem are you trying to solve?"



回答5:

The <script> tag order is important as @Sime Vidas mentioned.

Do the following order:

<script src="hutber.js"></script>
<script src="hutber.form.js"></script>

I modified the script in jsFiddle. You'll note that I like being explicit about global variables by using window.variable. I have the init function in the core hutber.js file firing immediately, if that's what you want.

//core hutber.js 
window.hutber = {}; // Explicit Global Variable

(function ($) {
    "use strict"; //For good development standards :)

    window.hutber.init = function(){
      alert('init fired');  
    };

    window.hutber.init(); // You can fire this anywhere since you set it on a global variable...
})(jQuery);

//Extra bits hutber.form.js
(function ($) {
    "use strict"; //For good development standards :)
    window.hutber.form = {prop: "hello im a form"}
    alert('window.hutber.form is now' + window.hutber.form.prop);
})(jQuery);