I see a lot of code like:
var myApp ={};
(function() {
console.log("Hello");
this.var1 = "mark"; //"this" is global, because it runs immediately on load. Caller is global
myApp.sayGoodbye = function() {
console.log("Goodbye");
};
})();
Which causes the anonymous function to execute immediately. But what is the advantage of this, compared to just putting the code inline?
var myApp ={};
console.log("Hello");
var1 = "mark";
myApp.sayGoodbye = function() {
console.log("Goodbye");
};
Apparently it's to do with scope of the function, but as the function is anonymous and called by window, it's scope (i.e. this) is global, no?
Usually, you would have this :
var myApp ={};
(function() {
console.log("Hello");
var var1 = "mark";
myApp.sayGoodbye = function() {
console.log("Goodbye");
};
})();
The main difference is that var1 doesn't clutter the global namespace. After this call, var1 is still the same than before (generally undefined).
As var1 can only be accessed from the function defineds in the closure, it is said "private".
Apart avoiding possible causes of conflicts, it's just cleaner not to keep global variables when useless.
Here, you don't have a local variable but a global one defined as this.var1. It's probably a bug, or the reason would be found elsewhere in the code.
One reason: wrapping your code in an anonymous function allows you to create a module which distinguishes a public API from private functions and variables that are only used internally to the module. This avoids polluting the global namespace.
var myApp ={};
(function() {
console.log("Hello");
this.var1 = "mark";
function helper() {/*Some code here*/;}
myApp.sayGoodbye = function() {
helper()
console.log("Goodbye");
};
})();
I could say:
var myApp ={};
console.log("Hello");
var var1 = "mark";
function helper() {/*Some code here*/;}
myApp.sayGoodbye = function() {
helper()
console.log("Goodbye");
};
But then the global scope includes a function called helper which is of no use to anyone using your module, and could lead to possible naming conflicts with other modules.
I could alternatively just include helper as a method of myApp.
var myApp ={};
console.log("Hello");
var var1 = "mark";
myApp.helper = function() {/*Some code here*/;}
myApp.sayGoodbye = function() {
this.helper()
console.log("Goodbye");
};
However, I may wish to prevent users from directly calling helper, in which case this won't do.
Related
A number of different articles around the web have been professing the greatness of using global import when designing modules (similiar to jQuery).
So, doing something like this...
(function(globalVariable){
globalVariable.printStuff = function(){
console.log(‘Hello World’)
};
}(globalVariable));
...means that I can call a function with something like this:
globalVariable.printStuff();
The problem is, whenever I run this in the console, I keep getting:
globalVariable undefined
My quesiton is, where exactly do I need to declare this variable so that I can get this to work?
For such a real simple module, you don't need any IIFE. Just write an object literal:
var globalVariable = {
printStuff: function() {
console.log('Hello World');
}
};
globalVariable.printStuff();
If you want to use an IIFE scope, you still have to create the object somewhere. That could be inside the module or outside:
var globalVariable = (function() {
var module = {};
var localVariable = 'Hello World';
module.printStuff = function() {
console.log(localVariable);
};
return module;
}());
globalVariable.printStuff();
var globalVariable = {};
(function(module) {
var localVariable = 'Hello World';
module.printStuff = function() {
console.log(localVariable);
};
}(globalVariable));
globalVariable.printStuff();
For a browser window object is the object that stores all the global variables. Below code shows a basic implementation of IIFEs with global variable.
//Set a variable 'globalVariable' in the window object
window.globalVariable = 10;
//Access the global variable 'globalVariable' in IIFE
(function(globalVariable) {
console.log(globalVariable);
})(globalVariable);
I have created an object and am attaching a bunch of functions to the object. I am concerned about how the ordering of the functions effects when I can call my functions. In my example below, I must define my functions first before I can use them. My problem with this is that I cannot call init() immediately until I have defined it. Init() will contain a bunch of other functions that it will need to call, which will have to be placed above init(). So in the end, init() will have to be the very last function defined in my object. I believe this is related to Hoisting.
My question is if there is a way for me to call a function before defining it? Is there some sort of way to create a 'placeholder' function like in C?
https://jsfiddle.net/13hdbysh/1/
(function() {
foo = window.foo || {};
//this will not error
foo.helloWorld = function() {
console.log('helloWorld()');
};
foo.helloWorld();
//this will error
foo.init();
foo.init = function() {
console.log('init()');
};
})();
What you're asking deals with how objects store member data. This can be seen in a weird light because of prototypal inheritance. Javascript by default will parse naked functions before they execute.
Example:
(function() {
init();
function init()
{
console.log("Init");
}
)};
This gets muddied when storing behavior as a member to an object. Because prototypal inheritances dynamic functionality you need to declare your members before accessing them. This is Javascript's main difference from traditional OOP languages.
You mentioned, "is there a way to create a 'placeholder' function like in C." You can, but not in the same way. You can assign it to a naked function and assign that to your object. Look in my example, the hello function.
Alternatively you can store the behavior on the prototype of your object and override it when necessary.
Example:
function hello()
{
console.log("Hello my name is "+this.name);
}
(function() {
var something = function(name) {
this.name = name;
};
something.prototype.initTwo = function() {
console.log("My Name is: "+this.name);
};
var thingOne = new something("Thing One");
thingOne.init = "SomeThing";
var thingTwo = new something("Thing Two");
thingTwo.init = function() {
console.log(this.name);
};
thingTwo.initTwo = function() {
console.log("SomethingTwo is Named: "+this.name);
};
thingTwo.hello = hello;
console.log(thingOne.init);
thingTwo.init();
thingOne.initTwo();
thingTwo.initTwo();
thingTwo.hello();
}) ();
Demo: Fiddle
Documentation on objects in javascript.
Try using similar IIFE pattern
(function() {
foo = window.foo || {};
//this will not error
foo.helloWorld = function() {
console.log('helloWorld()');
};
foo.helloWorld();
//this will error
// foo.init();
foo.init = (function _foo() {
console.log('init()');
this.init = _foo;
return this.init
}).call(foo);
foo.init()
})();
jsfiddle https://jsfiddle.net/13hdbysh/2/
I am not sure why would you wanna call it before it is defined but here is how to do it:
foo = window.foo || { init: function() { } };
How about declaring it as a local variable first.
(function() {
foo = window.foo || {};
//this will not error
foo.helloWorld = function() {
console.log('helloWorld()');
};
foo.helloWorld();
var initFunction = function() {
console.log('init()');
};
//this will no longer error
initFunction();
foo.init = initFunction;
})();
Init() will contain a bunch of other functions that it will need to call, which will have to be placed above init().
You are operating under a misapprehension.
A function must be defined before you call it, not before you define another function which will call it later.
Just define all your functions and then start calling them.
(function() {
foo = window.foo || {};
foo.helloWorld = function() {
console.log('helloWorld()');
};
foo.init = function() {
console.log('init()');
};
foo.init();
foo.helloWorld();
})();
As far as hoisting is concerned, function declarations (you only have function expressions) are hoisted, but they create locally scoped variables, not object properties. You would have to assign them to object properties before you could call them as such, and that assignment wouldn't be hoisted.
It's throwing an error because you're calling the method init() before it's declared.
This way will works
foo.init = function() {
console.log('init()');
};
foo.init();
Since foo is an object, you can put those functions into an object so that will be assigned to foo once window.foo is null
(function() {
foo = window.foo || {
helloWorld: function() {
console.log('helloWorld()');
},
init: function() {
console.log('init()');
}
};
//this will not error
foo.helloWorld();
foo.init()
})();
I have a very confusing situation...
(function sayStuff(){
this.word = "hello2";
(function (){
console.log(this.word);
}())
}())
var myObject = {
word: "bar",
func: function() {
(function() {
console.log(this.word);
}());
}
};
myObject.func();
Outputs
hello2
hello2
How is this happening? How can the closure on the 'func' of myObject actually see the variable that is referenced in sayStuff()? I thought IIFE were meant to protect internals from Global scope?
In both cases, this is window, the global default context replacing the one you don't provide when you call the internal function expressions.
If you want to keep the context, don't use IIFE internally or call them with the context :
(function sayStuff(){
this.word = "hello2"; // still this is window, use var if you don't want that
(function() {
console.log(this.word); // window.word
}).call(this); // well, this is window...
}())
var myObject = {
word: "bar",
func: function() {
(function() {
console.log(this.word); // myObject.word
}).call(this);
}
};
myObject.func();
IIFE only hide locally scoped variables (i.e. those created with the var keyword).
All your functions that touch this.word are invoked in the global context (i.e. not as methods of an object, not with the new keyword and not with apply, call or bind), so this is window in each case. You are dealing with global variables.
If you wanted a private variable you would do something more like this:
(function (){
var word = "hello2";
(function (){
console.log(word);
}())
}())
I am working on angularJs and working on javascript optimization.
I recently saw a video by YUI creator who is a javascript expert about javascript optimization. He explained about variable declaration and scopes and how javascript work. and How javascript engine has to look for variable from current scope till global scope to find it etc etc (Ref: http://jonraasch.com/blog/10-javascript-performance-boosting-tips-from-nicholas-zakas)
My question regarding is (not specific to angularjs) is:
when in my controller i declare a function like:
app.controller('Ctrl', function() {
var func1 = function() {
console.log("Hello");
}
this.func2 = function() {
console.log("World");
}
func1();
this.func2();
});
Which function should be faster ? I know its a overkill but I am interested in knowing how javascript engine works.
in terms of scope these two are identical (they are both local, not global). the difference is in functionality: the "this.func2" function is "public" (you could call that function with a reference to an instance of the Ctrl object), where as the "var func1" is a "private" function.
in terms of the speed of executing a call, I have put together this small test on jspref:
http://jsperf.com/private-vs-public-speed-js
Benchmark.prototype.setup = function() {
var obj = (function() {
this.f1 = function() {
console.log('a');
}
var f2 = function() {
console.log('a')
}
return {
f1: f1,
f2: f2
}
})();
};
comparing between "use public method"
obj.f1();
to
"use private method"
obj.f2(); does not seem to show a significant difference most of the time.
In the module pattern in JavaScript "Immediately-Invoked Function Expressions" (also known as self-executing anonymous functions) are used as self executing functions that return an object.
How can a self-executing function hide private variables and only expose the returned object. Why does this not happen with a normal JavaScript function?
So in the following mini module, why could we not achieve the same concept of encapsulation without the enclosing ()()?
var Module = (function () {
var privateVariable = "foo",
privateMethod = function () {
alert('private method');
};
return {
PublicMethod: function () {
alert(privateVariable);
privateMethod();
}
};
})();
How can a self-executing function hide private variables and only expose the returned object. Why does this not happen with a normal JavaScript function?
It does happen with normal JavaScript functions.
function MakeModule() {
var privateVariable = "foo",
privateMethod = function () {
alert('private method');
};
return {
PublicMethod: function () {
alert(privateVariable);
privateMethod();
}
};
}
var Module = MakeModule();
would work just fine.
The only difference is that the anonymous function introduces one less global variable and allows for itself to be garbage collected while MakeModule can't be collected unless explicitly deleted by the author.
The privateness is because of closures. The "var privateVariable" is closed over by "PublicMethod", so only that function can access the variable because only it has it in its closure. It cannot be referenced by anything else and is "private"
This happens not only in "Immediately-Invoked Function Expressions" but also in normal function calls. It is just a way to immediately create the closure when defining the module instead of doing it later when you call the outer function.
Also see this post from Douglas Crockford himself: http://javascript.crockford.com/private.html
You can define a anonymous function via named function.
Example:
//factorial
(function(n){
var self = function(n){
//call self
return n > 0 ? (self(n-1) * n) : 1;
}
return self;
})()