JS Scoping of functions / global variables - javascript

I read that it is usually best to include your javascript code within a function block like so
(function () {
"use strict";
// stuff here
}());
But if the code is meant to be globally accessible, a function or a constant for example, is that ok to be outside of a function block or should I set it up in another way?
Also - if I moved the code outside of the function block JSLint, for example, would suggest I move the use strict statement inside a function block. Would just have to be a concession I would have to make?

Setting things up inside of a function has benefits, it means that private variables which are not exposed remain private. You can expose things to the outside world by returning things from that function.
var module = (function() {
"use strict";
var private = "This is private!";
var publicFn = function() { return "This is public!"; };
return {
myFunction: publicFn;
};
})();
module.myFunction(); // This is public
As for using "use strict" only inside functions, it's because authors often concatenate and minify multiple JavaScript files, and using "use strict" outside the function scope will affect all other files in the chain (which is sometimes not the intended behavior and can cause bugs).

Related

Benefit of Immediately-invoked function expression (IIFE) over a normal function

I'm pretty new to javascript and I read about the module pattern to provide some sort of namespace and have both private and public members, for example:
var module = (function() {
var s = "Hello, i'm private and in closure!";
return {
myString : s,
myFunc: function() { alert(s); }
};
})();
I do see the benefits of that, because it gives you some of the advantages of object-oriented programming. But I've seen a lot of examples of an IIFE that doesn't get assigned to a variable. This (as far as I see) has no advantages at all compared to a normal function that you invoke:
1. IIFE
(function() {
var s = "Hello I'm private!";
$('#myButton').on('click', function() {
alert(s);
});
})();
2. Normal function
function Initialize() {
var s = "Hello I'm private!";
$('#myButton').on('click', function() {
alert(s);
});
}
Initialize();
They both have private variables that avoid the need of creating global variables and they both execute without returning any value to a variable.
Although the second one gives you the option of choosing a good name that says a lot more than a potential large IIFE without the name, leaving the reader to find out what's happening. The answer I see everywhere is 'to avoid namespace pollution' but both approaches do that, the first one is just a bit harder to understand?
In short:
What is the benefit of using an IIFE over a normal function that I'm missing? Why should I use them?
Sometimes you need to define and call function at the same time and only once so in this case anonymous function helps you. In such situations giving functions a name and then calling them is just excess.
Further sometimes you wants to create a namespace for your variables. So anonymous functions helps you there too. For example
(function($) {
$.fn.pluginName = function(opt) {
// implementation goes here...
}
}(jQuery));
In above case you can safely use $ as jQuery synonym in your code.
If you define a function with name as shown below, then it will create global variable with function name as you defined.
function myFunction() {
// function code goes here.
}
myFunction();
But if you define it without name then it won't create any global variable and your global namespace will not be polluted.
(function myFunction() {
// function code goes here.
}());
Function with names are useful only when you need to call them from different places in your code.

Clarify one JavaScript scoping regarding page 199 of Nicholas's "Maintainable JavaScript"

In Appendix A, page 199, when discussing using "use strict", it goes like this:
If you want strict mode to apply to mulitple functions without needing
to write "use strict" multiple times, use immediate function
invocation:
//good
(function() {
"use strict";
function doSomething() {
// code
}
function doSomethingElse() {
// code
}
}());
My question is, if this is what the whole anonlymous function looks like, then probably there is no effect (to the rest) of invoking it immediately? Because only two functions are declared within the anonymous function but it's neither called from within there (so the two functions cannot make any side effects to the rest of the world), nor returned to the outside so their references are lost.
Probably, I just want to confirm, that the code snippet is only intended to show the use of "use strict", so it simply omitted either the calls to, or return of, these two functions?
Thanks,
/bruin
The idea is that the IIFE encloses all of your code, not just those functions.
I think you are correct. This example is not a complete one because it will never call the functions defined in it. The example is just meant to illustrate how to apply "use strict" across a specific set of functions. If you wanted to extend it a bit so that the functions are exported, you could do something like this:
var myModule = (function() {
"use strict";
function doSomething() {
// code
}
function doSomethingElse() {
// code
}
return {
doSomething: doSomething,
doSomethingElse: doSomethingElse
};
}());
myModule.doSomething();
myModule.doSomethingElse();

The way of good scoping in JavaScript

I am not a really good JavaScript user but I can get things done with it. I am not proud of the code I have written in JavaScript, so I decided to change that. Here is my first step:
I am trying create my own library for a project and the below is the initial structure.
window.fooLib = {};
(function (foo) {
"use strict";
foo.doSomeStuff = function(param1) {
console.log(new AccommProperty(param1));
}
//some internal function
function AccommProperty(nameValue) {
var _self = this;
_self.name = nameValue;
}
}(fooLib));
I used immediately invoked function expression here to initialize my variable. In this case it is fooLib.
I am not sure if I should do some other things to make window.fooLib more safe. I mean it can be overridden by any other code which will run after my code if I understand JavaScript correctly.
What are your thoughts?
If you want to prevent overwriting your variables, you may use Object.defineProperty() with writable:false, configurable:false. In your case:
(function () {
"use strict";
var foo = {};
//some internal function
function AccommProperty(nameValue) {
var _self = this;
_self.name = nameValue;
}
foo.doSomeStuff = function(param1) {
console.log(new AccommProperty(param1));
}
Object.defineProperty(window, "foolib", {value:foo});
}());
Still, there is no good reason for that. It would need EcamScript 5.1 to work, and there are no shims around; maybe something with getters/setters to prevent overwriting with the = operator.
But also, there should be no need to make your library un-overwritable. Just don't use code on your site that overrides the lib. Or maybe someone even wants to overwrite your functions with another, better lib with the same interface?
If the question is about a library to be shared, with possible namespace conflicts to others, you may have a look at jQuery.noConflict.
Every JavaScript object can be overriden. This is the nature of JavaScript and it is impossible to change it. So you cannot make your code safe in that sense.
As for selfinvoked functions: you should use them when you want to have local variables but viisible to all your functions. So in your case AccommProperty is such variable. Defining doSomeStuff inside scope makes no difference unless doSomeStuff will use variables defined inside scope.
So when you want to hide variables from user and/or you need globals and you are affraid of name conflicts use selfinvoked functions.
I am not sure if I should do some other things to make window.fooLib more safe. I mean it can be overridden by any other code which will run after my code if I understand JavaScript correctly.
You could try making window.fooLib a local variable instead. Using closures and nested functions one can emulate a namespace where you can put all your data instead of putting it into the global scope or attaching it to window object:
(function() {
// all functions nested in foo() have access to fooLib.
fooLib = {}
fooLib.doSomeStuff = function(param1) {
console.log(param1);
console.log(fooLib);
}
//some internal function
function AccommProperty() {
console.log(fooLib);
}
}());
See Javascript Closures: Encapsulating Related Functionality for more details.

How to declare global variables when using the strict mode pragma

It's considered good practice to use a self-invoking function to wrap strict mode compliant code, often called the strict mode pragma:
(function(){
"use strict";
// Strict code here
}());
My question is how to declare global variables in this case? Three alternatives that I know of today:
Alternative 1:
var GLOB = {};
(function(){
"use strict";
}());
Alternative 2:
(function(){
"use strict";
window.GLOB = {};
}());
Alternative 3:
(function(win){
"use strict";
win.GLOB = {};
}(window));
Any preferences and motivations? Other options?
IMO alternative 3 is best. But it assumes that window represents the global scope - which is true for the browser but not for other JS environments (command line, Node.js, etc.).
The following will work across the board:
(function(globals){
"use strict";
globals.GLOB = {};
}(this));
I know this is an old question but there's one not mentioned way of getting global context:
(function(globals){
"use strict";
globals.GLOB = {};
}( (1,eval)('this') ));
(1,eval)('this')
will evaluate this from global context, so you can paste this wherever you like and you will always get global context
Method 1 would fail if it's pasted in another function.
Using method 3, it is easier to export your methods to another namespace. Simply replacing window with, say, frames[0] or document is enough to attach all methods to a custom namespace.
I recommend method 3, for the last reason.
Benefit of alt 2 and 3 is that they keep all of the code inside the "container function." One line of code outside of the function is easy to miss when reading the code.
Also:
"GLOB" should be the application's name. -- You want to allow for more than one application per html/js file without name collisions.
Andrea Giammarchi has a nice technique for doing this, that works across browsers. Define a function in your self-invoking function called globalEval like so:
(function () {
"use strict";
function globalEval(data) {
data = data.replace(/^\s*|\s*$/g, "");
if (data) {
var head = document.getElementsByTagName("head")[0] || document.documentElement,
script = document.createElement("script");
script.type = "text/javascript";
script.text = data;
head.appendChild(script);
head.removeChild(script);
}
}
// use globalEval to stick variables into the global scope
globalEval("var myGlobal = 1;");
// myGlobal === 1
)();
// myGlobal === 1
Or define the globalEval function outside of the self-invoking code if you want to use it in other scopes.

Accessing a function defined inside a function from the global scope?

Long story short, I have a long code that uses jQuery. Lots of files, functions, etc. A less than ideal amount of our users are having issues with our code because some addons, toolbars and the like they have installed breaks our JavaScript code because of jQuery gets included twice and nasty stuff like that.
I thought I could just
Include jQuery
Use $.noConflict
Then include the whole rest of my code between something like:
.
(function($) {
// All of my code goes here.
})(jQuery);
I haven't checked if this fixes our issues with those users, but it does work. The problem is, in one part of the site (image upload) we have an iframe that needs to call some of those functions defined in our big chunk of code. I've tried putting those functions out of this unnamed function call, but it uses, on itself, other functions which have to be there.
Any idea or workaround of how could I be able to access functions defined inside that function (shown above) from a code that's outside of it?
Thanks!
You cannot access a function context from the "outside world". Well, to be accorate you could do it in some older js engines which allowed for accessing .__parent__ attributes, but that is old'n'busted and no longer available.
However, you would need to either expose some functions within your closure, or you creating a namespace object where you write all of your logic in (which also has to be available in the parent context).
So I'd suggest something like
(function( $ ) {
function myFunc() {
// do stuff
}
function anotherFunc() {
}
window.myFunc = myFunc; // expose myFunc globally
}( jQuery ));
Maybe even better:
var myNameSpace = { };
(function( $ ) {
myNameSpace.myFunc = function() {
// do stuff
};
}( jQuery ));
// somewhere else
myNameSpace.myFunc();
It is not an ideal practice, but you can declare those functions in the global scope.
(function($) {
globalFunct = function (arg1, arg2) { // Don't use var keyword
...
};
})(jQuery);
It isn't ideal because you can run into naming collisions, much like you are observing with jQuery. Improve upon this approach by putting all of your globally-accessible methods in a "package." Choose a unique name for it. This will prevent collisions.
// Somewhere outside of your anonymous function, in the global scope
var myPackage = {};
(function($) {
myPackage.globalFunct = function (arg1, arg2) {
...
};
})(jQuery);
Then call that method by invoking myPackage.globalFunct().
Why are you wrapping your code in a call to the jQuery function object which you pass in to your self-executing anonymous function; are you meaning to create a jQuery object from all of your code?
In order to expose your code to the outside world, you need to assign your functions and objects to an object which is outside of the scope of your code, such as the window object.
For example, if you had created an object containing various methods and properties that you wanted to expose, you could do this:
//Your self-executing anonymous function
(function($)
{
//Object which contains various useful methods and properties
var useful = {...};
//Expose it to the outside world
window.Useful = useful;
})(jQuery);
EDIT: as others have noted, it is not an ideal solution as you will indeed run into naming collisions if you are not careful. Also, using an object external to your anonymous function as a namespacing object (as others have stated) is my preferred method
Yes, you can "export" the function from within a closure:
Yes, you can "export" the function from within a closure:
(function() {
function a() {
console.log("a");
}
function b() {
a();
console.log("b");
}
// make b globally available
window.b = b;
})();
b();
window.PARTY_CATS_jQuery = jQuery.noConflict(true);
(function($) {
$(function() {
// All of my code goes here.
});
})(COMPANY_NAME_jQuery);
Then just use PARTY_CATS_jQuery in your global functions
If you feel PARTY_CATS_ is not a unique enough name pick something safer like BABY_KILLER_jQuery

Categories

Resources