-1

I was just going through this code here, it describes how to create your own custom ready function in pure js. The answer is explained in great detail, I have been programming in js for a while now, but still have a problem understand the initial part of the code, Have a look at the code below again :

(function(funcName, baseObj) {
    // The public function name defaults to window.docReady
    // but you can pass in your own object and own function name and those will be used
    // if you want to put them in a different namespace
    funcName = funcName || "docReady";
    baseObj = baseObj || window;
    var readyList = [];
    var readyFired = false;
    var readyEventHandlersInstalled = false;

    // call this when the document is ready
    // this function protects itself against being called more than once
    function ready() {
        if (!readyFired) {
            // this must be set to true before we start calling callbacks
            readyFired = true;
            for (var i = 0; i < readyList.length; i++) {
                // if a callback here happens to add new ready handlers,
                // the docReady() function will see that it already fired
                // and will schedule the callback to run right after
                // this event loop finishes so all handlers will still execute
                // in order and no new ones will be added to the readyList
                // while we are processing the list
                readyList[i].fn.call(window, readyList[i].ctx);
            }
            // allow any closures held by these functions to free
            readyList = [];
        }
    }

    function readyStateChange() {
        if ( document.readyState === "complete" ) {
            ready();
        }
    }

    // This is the one public interface
    // docReady(fn, context);
    // the context argument is optional - if present, it will be passed
    // as an argument to the callback
    baseObj[funcName] = function(callback, context) {
        // if ready has already fired, then just schedule the callback
        // to fire asynchronously, but right away
        if (readyFired) {
            setTimeout(function() {callback(context);}, 1);
            return;
        } else {
            // add the function and context to the list
            readyList.push({fn: callback, ctx: context});
        }
        // if document already ready to go, schedule the ready function to run
        if (document.readyState === "complete") {
            setTimeout(ready, 1);
        } else if (!readyEventHandlersInstalled) {
            // otherwise if we don't have event handlers installed, install them
            if (document.addEventListener) {
                // first choice is DOMContentLoaded event
                document.addEventListener("DOMContentLoaded", ready, false);
                // backup is window load event
                window.addEventListener("load", ready, false);
            } else {
                // must be IE
                document.attachEvent("onreadystatechange", readyStateChange);
                window.attachEvent("onload", ready);
            }
            readyEventHandlersInstalled = true;
        }
    };
})("docReady", window);

and i am calling the code like so:

docReady(function() {
        alert('hello');
  }, window); 

My question is, how can you call a anonymous function , like so ? .. i am totally confused :(

How on earth does even the below code work ?

docReady(function() {
        alert('hello');
  }, window);

I mean there is no explicit docReady function defined , like so:

  docReady function (param1, param2);

all i see is docReady being passed as a parameter to the anonymous function ?

Community
  • 1
  • 1
Alexander Solonik
  • 8,718
  • 13
  • 56
  • 133
  • 1
    `baseObj[funcName]` declares the function (edit: I made an answer to make it clearer). – Denys Séguret Jul 21 '15 at 14:03
  • 1
    What he said. In the above code, `baseObj` is `window`, and `funcName` is `"docReady"`, so it's `window["docReady"] = function()...`, which is the same as `window.docReady = function() ...` – Paul Roub Jul 21 '15 at 14:04

3 Answers3

3
baseObj[funcName] = function(callback, context) {

is equivalent to

window["docReady"] = function(callback, context) {

It declares the function as a property of window, the global object, which means you can call it with

window["docReady"](function() {
    alert('hello');
}, window);

or with

window.docReady(function() {
    alert('hello');
}, window);

or even

docReady(function() {
        alert('hello');
}, window);

as properties of the global object are also variables of the global scope (and any scope inside until shadowed).

Denys Séguret
  • 335,116
  • 73
  • 720
  • 697
2

The key bit is baseObj[funcName] = function

at this point baseObj is (or at least can be) window, and funcName is (or can be) docReady.

So at that point it adds a function to window (global) called "docReady"

window and "docReady" are being passed as default parameters on the last line

})("docReady", window);

which enter the function at the top as parameters (function(funcName, baseObj) {

N.B. When I say baseObj is (or at least can be) window, that's because you can override this value, this line:

funcName = funcName || "docReady";
baseObj = baseObj || window;

set's funcName to "docReady" and baseObj if an alternative isnt provided, that means that you can change them if you like, so if the last line was changed to })("getReady", myObject); the function would be called getReady and be added to the myObject, not the global window

atmd
  • 7,034
  • 2
  • 28
  • 62
0

You are reading the code wrong.

Check these lines:

(function(funcName, baseObj) {
    ...
    baseObj[funcName] = function(callback, context) {
        ...
    };
    ...
})("docReady", window);

It is adding a new property to the baseObj, which in this case is window. That property is the function you call. The docReady. Everything that is global doesn't need to be called like window.something. That's why you use docReady.

Ismael Miguel
  • 3,941
  • 1
  • 27
  • 35