Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing a window object into Javascript namespace

I'm trying to better understand namespacing in javascript and found an example of a javascript Immediately-invoked Function Expression that is taking the window object as a parameter. Here is the code from it:

var CG = CG || {};
CG.main = (function(window) {
    var FOCAL_LENGTH = 8.0;
    var context, width, height, startTime;

    var init = function() {
        var element = document.getElementById("canvas1");
        context = element.getContext("2d");

        width = element.width;
        height = element.height;

        startTime = (new Date()).getTime() / 1000.0;
        tick();
    }

var original_onload = window.onload || function() {};
    window.onload = function() {
        original_onload();
        CG.main.init();
    }
    return {
        init: init,
        draw: draw_shape,
        clear: clear_canvas
    };
}(window));

At the end of the namespace definition, there is a line with window in parenthesis which I am confused as to the functionality of. I think that the purpose of adding the parameter of window to the end of the definition is to bind the global window variable to the namespace which will then add different properties to the window, but I can't really be sure.

In another example there is a random variable name passed into the definition of a namespace, and at the end of the namespace definition, the actual name of the namespace is passed as a parameter:

var namespace = namespace || {};
// here a namespace object is passed as a function
// parameter, where we assign public methods and
// properties to it
(function( o ){
    o.foo = "foo";
    o.bar = function(){
        return "bar";
    };
})(namespace);
console.log(namespace);

So there are really a couple of questions here:

  1. What is the functionality of passing a parameter at the end of the namespace definition?

  2. If my intuition for how this all works is incorrect, what is the general structure for this kind of namespace creation javascript?

Clearly I'm very new to this so any help would be appreciated, thanks.

like image 582
loremIpsum1771 Avatar asked Nov 01 '15 01:11

loremIpsum1771


People also ask

Can you pass object to JavaScript function?

We can pass an object to a JavaScript function, but the arguments must have the same names as the Object property names.

How do you pass data into an object in JavaScript?

Begin by creating a JavaScript object. Populate your JS object with your chart configuration. var dataObj={ type: "line", title: { text: "Chart Data Object" }, series: [ { values: [69,68,54,48,70,74,98,70,72,68,49,69] } ] }; Pass the object into your zingchart.


1 Answers

I will try to explain this as well as I can but my understanding of it comes from Kyle Simpson. He's awesome, you should look him up. :-D

You are asking a question about immediately invoked function expressions (IIFE), passing arguments to them, and why someone would do that.

First, the reason IIFEs are being used in this context is to restrict the scope of variables.

This is important because as programs become larger and many pieces are added on you can easily have conflicts from one variable to another.

app.js could have

variable = "thing";

and shortly after somethingelse.js could have

variable = "not thing";

That is a huge problem. It is avoided in javascript by creating "modules" or functions that immediately run and run once.

That way, the variables and methods you create in your function don't "pollute the global scope/namespace."

BUT, what if you NEEDED or WANTED something to be available on the global window object?

Well, you could do that by adding it to the "window" which is the global scope in javascript.

(function Module(window){
   var _thing = "private thing that only exists in this function";
   window.thing = _thing;
      //IS NOW AVAILABLE GLOBALLY AND EXPLICITLY ON WINDOW OBJECT
      //window.onload you can wait for DOM/page before running the rest
})(window);

You also could have named it anything you wanted inside your function:

(function niftyModule(global){

    global.variable = "nifty text!";

})(window)

This becomes especially important when you are using multiple libraries.

For some reason, everyone likes to use "$" as the representation of their library so you can access their private methods (which are really just functions inside an IIFE too! (its a really popular way to build good stuff).

So, what if you are using jQuery and 2 other libraries that also use $ to access their public methods/api??

Easy, you can assign which one you want to assign what variable inside your function/module scope by passing it in as an argument!

(function NiftyModule(window, $){

 //Now, every time you use $ in here it means jQuery and not something else!

})(window, jQuery);

It is important to play around with functions and scope. Build some variables in different ways.

For example, is....

var text = "nifty text";

the same as

text = "nifty text";

How about if you do the same thing inside functions? How do those two versions differ?

Also, get used to building your own programs in IIFEs and properly restricting the scope of the code you are writing.

You can also return objects from functions which have the methods and variables you want to access globally on them without adding them to the window object.

It is complicated at first but in the future it saves you a lot of trouble and bugs!

Finally, In your example of:

//initialize a global variable called namespace. If this already
//existed then assign it the previous values. If not, make it an empty
//object.
var namespace = namespace || {};

//pass namespace into an IIFE. Within the IIFE refer to namespace as "o"
(function( o ){
    //assign a variable to namespace
    o.foo = "foo";

    //assign a method to namespace
    o.bar = function(){
        return "bar";
};
})(namespace);

//now when you log namespace it will have those properties.
console.log(namespace);
like image 186
Chris L Avatar answered Oct 05 '22 11:10

Chris L