Javascript IIFE, don't understand how this variable becomes global - javascript

Take the following block of code. There is no return statement, and yet MyApp.VideoTracker is a property on the window object and so is accessible globally.
(function(window, $, VideoTracker, undefined) {
"use strict";
VideoTracker.loadAPI = function(apiReadyCallbackFn) {
};
VideoTracker.destroy = function(iframeElement) {
};
VideoTracker.trackVideos = function() {
};
$().ready(function() {
var youTubeIframes = $('iframe[src*="youtube.com"]');
if (youTubeIframes.length > 0) {
VideoTracker.loadAPI(VideoTracker.trackVideos);
}
});
}(window, jQuery, MyApp.VideoTracker = MyApp.VideoTracker || {}));
Is this because of the way it is defined in the function call, i.e.:
MyApp.VideoTracker = MyApp.VideoTracker || {}
An explanation would be great, as I can see this must be the reason but don't understand why?

Yes, essentially you're calling the IIFE with what are global variables.
Assuming you've defined MyApp already - and before the function body is executed - you're calling it with an expression that either sets the VideoTracker property of MyApp with the existing MyApp.VideoTracker or an empty object literal, and that reference is being passed into your IIFE.
Hope that helps.

That's because your MyApp is a Global object already- it doesn't become one, because of your self invoked function.
How else do you think you would be able to access its VideoTracker property or define it if it's not there?
In a case in which MyApp object doesn't exist as a part of a higher context in which your IIFE is being executed, it should rise a Reference Error! because MyApp object is neither defined, nor being created within your given IIFE context.

Related

What is a "scoping function" in javascript?

In Learning Javascript Design Patterns, the author says
Object literals don't require instantiation using the new operator but
shouldn't be used at the start of a statement as the opening { may be
interpreted as the beginning of a block. Outside of an object, new
members may be added to it using assignment as follows
myModule.property = "someValue";
Below we can see a more complete example of a module defined using
object literal notation:
var myModule = {
myProperty: "someValue",
// object literals can contain properties and methods.
// e.g we can define a further object for module configuration:
myConfig: {
useCaching: true,
language: "en"
},
// a very basic method
saySomething: function () {
console.log( "Where in the world is Paul Irish today?" );
},
// output a value based on the current configuration
reportMyConfig: function () {
console.log( "Caching is: " + ( this.myConfig.useCaching ? "enabled" : "disabled") );
},
// override the current configuration
updateMyConfig: function( newConfig ) {
if ( typeof newConfig === "object" ) {
this.myConfig = newConfig;
console.log( this.myConfig.language );
}
}
};
// Outputs: Where in the world is Paul Irish today?
myModule.saySomething();
// Outputs: Caching is: enabled
myModule.reportMyConfig();
// Outputs: fr
myModule.updateMyConfig({
language: "fr",
useCaching: false
});
// Outputs: Caching is: disabled
myModule.reportMyConfig();
Using object literals can assist in encapsulating and organizing your
code and Rebecca Murphey has previously written about this topic in
depth should you wish to read into object literals further.
That said, if we're opting for this technique, we may be equally as
interested in the Module pattern. It still uses object literals but
only as the return value from a scoping function.
My Question:
What does he mean by "It still uses object literals but only as the return value from a scoping function."
Specifically what is a "scoping function"?
In JavaScript, variables declared with var are "function scoped" not "block scoped" like in other C-like languages (and how the {} syntax might imply). (Update Re: block scoping: ES6 introduced block scoping with two new variable declarations, let and const. See https://www.freecodecamp.org/news/var-let-and-const-whats-the-difference/)
To create a module with a "scoping function" means to use a function to wrap the scope of variables and other logic you may use, and then return an object literal with the results you want.
Example:
function personFacory(name) {
var person = {
name: name
};
if (name === 'Bob') {
person.isBob = true;
}
return person;
}
The case of the IIFE and closure #Josh mentions is also a valuable use of a "scoping function."
Another example:
var generateId = (function(){
var currentId = 0;
return function() {
return currentId++;
};
})();
Each time you call generateId(), it will return the next integer.
Pretty sure it's referring to an immediately invoked function expression, so that all the data present in the module is "scoped" (private, not affecting the global scope, whatever you wanna call it):
var somethingInTheGlobalScope = true;
var myModule = (function() {
var somethingThatOnlyExistsHere = true;
return {
myModuleMethod1: function() {},
myModuleMethod2: function() {}
}
})();
This IIFE is almost equivalent to just writing out a module in object literal notation, except with this pattern, you get the benefit of scopes not colliding with each other (i.e., any scope outside of your IIFE stays separate from the scope within the IIFE).
Note from Addy Osmani:
The Module pattern encapsulates "privacy", state and organization using closures.
Well in javascript we have a thing called function scope which means that the variable declared within a function are visible only within that function, more on scopes and hoisting here https://www.digitalocean.com/community/tutorials/understanding-variables-scope-hoisting-in-javascript Before ES6 the only way to create modules with isolated functions and variables from the global scope so they cannot override already existing functions and variables with the same names was to wrap the functionality you want to isolate in an IIFE (Immediately Invoked Function Expression) https://developer.mozilla.org/en-US/docs/Glossary/IIFE. These are functions that run as soon as they are defined and create an isolated scope of variable and function that isn't visible to the "outside world" or said otherwise the global scope i.e.
function sayHello() {
var name = "Viktor"
var personModule = (function() { //Here we define our IIFE
var name = "Adam";
return { //Here we return an object literal with a scoping function
sayHello: function() {
console.log("Hello my name is " + name);
}
}
}())
personModule.sayHello() //This will print "Hello my name is Adam"
console.log("Hello my name is " + name) //This will print "Hello my name is Viktor"
}
sayHello();
In the sample above first we define a sayHello function in the global scope and after that in it we define an IIFE that returns an object literal with the function sayHello in it and assign it to a variable called personModule. The function personModule.sayHello creates a closure because it holds a reference to the name variable of the IIFE scope. The IIFE is already executed but the function scope of the IIFE function remains in memory and it isn't collected by the garbage collector because the personModule.sayHello function will be executed outside the lexical scope where the function is defined and the reference to the name variable keeps this function scope alive. Said in other words personModule.sayHello keeps a reference to the surrounding state where the function is defined and this behavior is called a closure context https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures. At the end, we have to name variables one with the value "Viktor" that is defined in the global sayHello function's scope and one with the value "Adam" that lives in IIEF function scope and it is not visible to the outer scopes including the global scope. The only way to access this variable is through personModule.sayHello. This way the one name variable does not override the other name variable and both variables exist with different values in different scopes.

Object in strict mode

I have an object and I need it to run the content of the page. I need to wrap it with strict mode. I tried to return it to use in global scope, but it didn't solve my issue.
(function($) {
"use strict";
var MyObj = {
// some code here.
}
return MyObj;
})(jQuery);
console.log(MyObj); // <= undefined
How can I access to this object from anywhere of my project?
What you have there is an immediately-invoked function expression (IIFE) which is specifically designed to keep things separate from the external scope. Since you're returning MyObj, all you have to do to make it available in the global scope is this:
var MyObj = (function($) {
"use strict";
var MyObj = {
// some code here.
}
return MyObj;
})(jQuery);
console.log(MyObj);
The other way to do this would be to put MyObj in the global space explicitly. In a browser, the global object is called window, so you could, inside your IIFE, say window.MyObj = { /* some code here */ }. I would discourage this approach, though, because it's not clear to the outside observer that that's happening (i.e., you would have to rely on documentation). The better approach is to return the objects you want to expose, and the caller can choose to put those in global space.
Using use strict, you can only put an Object in int the global namespace explicitly.
For example, you could use window.myObj = MyObj in your function.
Another possible way to achieve your goal is by passing the global object to your function (it could be window in the browser or global in nodejs).
(function($, global) {
"use strict";
var MyObj = {}
global.myObj = MyObj;
})(jQuery, window);
Moreover, as Ethan suggested, since you return MyObj, you could simply assign the result of the invocation to a variable.
var myObj = (function($) {
"use strict";
var MyObj = {}
return x
})(jQuery);
myObj; //now defined in the global scope

what is self-executing anonymous function or what is this code doing?

var module = {};
(function(exports){
exports.notGlobalFunction = function() {
console.log('I am not global');
};
}(module));
function notGlobalFunction() {
console.log('I am global');
}
notGlobalFunction(); //outputs "I am global"
module.notGlobalFunction(); //outputs "I am not global"
Can anyone help me understand what's going on here? I get that if you call notGlobalFunction(), it will just call the second function.
But what is var module = {} doing? and why is it called again inside the first function?
It says this is commonly known as a self-executing anonymous function but I don't really know what that means.
Immediately invoked functions are typically used to create a local function scope that is private and cannot be accessed from the outside world and can define it's own local symbols without affecting the outside world. It's often a good practice, but in this particular case, I don't see that it creates any benefit other than a few more lines of code because it isn't used for anything.
This piece of code:
(function(exports){
exports.notGlobalFunction = function() {
console.log('I am not global');
};
}(module));
Would be identical to a piece of code without the immediate invocation like this:
module.notGlobalFunction = function() {
console.log('I am not global');
};
The one thing that is different is that in the first, an alias for modules called exports is created which is local to the immediately invoked function block. But, then nothing unique is done with the alias and the code could just as well have used modules directly.
The variable modules is created to be a single global parent object that can then hold many other global variables as properties. This is often called a "namespace". This is generally a good design pattern because it minimizes the number of top-level global variables that might conflict with other pieces of code used in the same project/page.
So rather than make multiple top level variables like this:
var x, y, z;
One could make a single top level variable like this:
var modules = {};
And, then attach all the other globals to it as properties:
modules.x = 5;
modules.y = 10;
modules.z = 0;
This way, while there are still multiple global variables, there is only one top-level global that might conflict with other pieces of code.
Similarly, an immediately invoked function creates a local, private scope where variables can be created that are local to that scope and cannot interfere with other pieces of code:
(function() {
var x, y, z;
// variables x, y and z are available to any code inside this immediately invoked function
// and they act like global variables inside this function block and
// there values will persist for the lifetime of the program
// But, they are not truly global and will not interfere with any other global
// variables and cannot be accessed by code outside this block.
// They create both privacy and isolation, yet work just as well
})();
Passing an argument into the immediately invoked function is just a way to pass a value into the immediately invoked function's scope that will have it's own local symbol:
(function(exports) {
// creates a local symbol in this function block called exports
// that is assigned an initial value of module
})(module);
This creates a new empty object:
var module = {};
It does the same as:
var module = new Object();
This wrapper:
(function(exports){
...
}(module));
only accomplishes to add an alias for the variable module inside the function. As there is no local variables or functions inside that anonymous function, you could do the same without it:
module.notGlobalFunction = function() {
console.log('I am not global');
};
An anonymous function like that could for example be used to create a private variable:
(function(exports){
var s = 'I am not global';
exports.notGlobalFunction = function() {
console.log(s);
};
}(module));
Now the method notGlobalFunction added to the module object can access the variable s, but no other code can reach it.
The IIFE is adding a method to the module object that is being passed in as a parameter. The code is demonstrating that functions create scope. Methods with the same name are being added to a object and the the head object (window) of the browser.
"self-executing" might be misleading. It is an anonymous function expression, that is not assigned or or given as an argument to something, but that called. Read here on Immediately-Invoked Function Expression (IIFE).
what is var module = {} doing?
It initializes an empty object that is acting as a namespace.
why is it called again inside the fist function?
It is not "called", and not "inside" the first function. The object is given as an argument ("exports") to the IEFE, and inside there is a property assigned to it.

Javascript self calling anonymous function for scope closure [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
What advantages does using (function(window, document, undefined) { … })(window, document) confer?
I'm increasingly seeing code like this in libraries I've been using:
(function (window) {
var Foo = function () {
}
window.Foo = Foo;
})(window);
The argument I've seen for doing this is to avoid working in the global scope when creating (pseudo) classes. But, correct me if I'm wrong, I always understood that window IS the global scope. I believe, when you create a global variable, you are really only adding a property to window anyway... Unless this is changing for ES5 strict?
So, basically, what's the point? The only benefit I can see to code organised like this is if you wanted to easily change the namespace of your classes at a later date by passing in an argument other than window.
Infact, strict mode throws an exception if you forget to use var for any variable declaration. But that works even without using an outer closure.
Using this pattern is much more for protecting yourself from the outside javascript world. For instance, some other script overwrites window.undefined or any other variable, you can grab the value within that closure to savely access it from within.
For instance
(function _myApp( win, doc, undef ) {
// app code
}( this, this.document ));
Also, when declaring variables with var, or creating function declarations, those are always stored within the current Activation Object respectively the Lexical Environment Record. That means, without using a Function context, you can easily overwrite methods and variables from some other point, because all of those would get stored in the current Context (which would be the global one)
So:
(function _myApp( win, doc, undef ) {
var myVar = 42;
function myFunc() {
}
}( this, this.document ));
(function _myModule( win, doc, undef ) {
var myVar = 42;
function myFunc() {
}
}( this, this.document ));
This works because of closure and Context, but if you would use the same code, without the Function Context, we would obviously overwrite our myVar and myFunc. This could happen from everywhere, within the same file or in another loaded script.
As evil as global variables are, you need to have atleast one or there's no way to access your script. The code you provided is one way to create that one global variable. I prefer this way:
window.Foo = (function () {
var func = function () {
// ...
};
return {
func: func
};
})();
Your're right, but the difference is that the code inside of the function acts like an automatic init function.
(function (window) {
var Foo = function () {
}
var Bar = 69; // not in global scope
window.Foo = Foo; // in global scope
})(window);
As opposed to
var Foo = function () { // in global scope
}
var Bar = 69; // in global scope
and
var Foo = function () { // in global scope
}
function init () {
var Bar = 69; // not in global scope
}
init();

unexpected behavior when creating global variable without var keyword

Here i am just creating a global namespace for my application and everything works as expected
var MYAPP = MYAPP || {} ;
but if I omit var keyword ( i know it's not the right way), javascript throw an error "ReferenceError: MYAPP2 is not defined" .
MYAPP2 = MYAPP2 || {};
just out of curiosity can some one explain me in second case why javascript is not able to resolve the reference.
The first version doesn't produce an error because Javascript's variable hoisting makes it equivalent to this:
var MYAPP; // declares, but leaves the value undefined / unchanged
MYAPP = MYAPP || {}; // creates, if the value was previously undefined
Importantly, the declaration part of this does not overwrite any existing declaration or assignment that was already made to the variable.
This is what allows this pattern to be used repeatedly within a single scope. MYAPP either retains the value it already had, or is initialised to an empty object.
in the second case, that declaration step is effectively omitted. If the variable has not already been declared (or otherwise exists in scope, i.e. as a property of the global object) then the error you see is generated.
var MYAPP = MYAPP || {} declares variable MYAPP in current scope (aka execution context). If declaration appears in a function - local variable is declared; if it's in global scope - global variable is declared.
MYAPP2 = MYAPP2 || {}, on the other hand, is merely a property assignment. It first tries to resolve MYAPP2 against scope chain. If it finds it anywhere in that scope chain, it performs assignment; if it doesn't find MYAPP2, only then it creates x property on a global object (which is a top level object in a scope chain).
var keyword declare immediately variable you are referencing to
var a = a || {};
is like as
var a; a = a || {};
In second case you are refencing to variable isn't declared yet.

Categories