How to declare global variables when using the strict mode pragma - javascript

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.

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.

JS Scoping of functions / global variables

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).

Self-executing anonymous functions and closures

information
I am trying to build a site where I can include certain files and append to my global variable with different methods that will just add easily to the object. Meaning I only need to include the file and this page will now have access to everything in the hutber object.
core hutber.js
var hutber = {};
(function ($) {
"use strict"; //For good development standards :)
hutber.init = function(){
};
hutber.init();
})(jQuery);
extra bits hutber.form.js
(function ($) {
"use strict"; //For good development standards :)
hutber.form = {
}
});
problem
I am aware that the hutber will not have access to hutber.form as it within a closure. So without taking these out of selfexecuting functions how can I get hutber to have access to hutber.form?
Or is this just the complete wrong way to approach this?
No it will have access to hutber.form since hutber is global, but the problem is timing.
If the init() runs before the hutber.form function is executed, it will not be there. The init can not run to all of the "add-ons" are loaded.
A side note: your second one will not run since it has no (jQuery);.
(function ($) {
"use strict"; //For good development standards :)
hutber.form = {
}
}); <-- missing (jQuery); so it is not going to do anything
Run a little demo to see what happens.
var myObj = {};
(function(){
myObj.init = function(){
alert("init");
try{ //will fail since bar has not loaded yet
myObj.bar();
} catch(e){ alert("failed calling bar"); }
};
//call init before bar is loaded
myObj.init();
})();
(function(){
myObj.bar = function(){
alert("bar");
};
})();
//call init after bar has been loaded
myObj.init();
jsFiddle of above code
When you run this, you will see that the init will fail the first time it is called since bar is not loaded. The second time it will work since the method is added. So if the init depends on the loaded "modules" it needs to know when they are loaded in order to call the init method.
I think you want this:
<script src="hutber.js"></script>
<script src="hutber.form.js"></script>
<script> hutber.init(); </script>
Seeing as how you defined hutber as a global variable the "form" property will certainly be accessible within any immediately invoked function expression.
You might be looking at this the wrong way.
Not to say that immediately-invoked functions are the wrong way to build functionality...
What I am saying, however, is that you've got a globally-available object, which you're referencing directly from within your function...
After you assign hutber.form = {};, everything in whole world of the global scope has full access to hutber.form, because hutber is globally-accessible.
It really wouldn't be any different than if you went like:
//form.js
hutber = hutber || {};
hutber.form = { /* ... */ };
In terms of public access to hutber.form.
The closure covers the things you DON'T return and the things that you DON'T assign to objects/arrays/vars in an outer-scope.
So if you had var mySecretIdentity = "Jerry O'Connell"; inside of the closure, then only the methods inside of hutber.form could access mySecretItentity...
...but again, you could accomplish the same by doing something like:
// form.js
hutber = hutber || {};
hutber.form = (function () {
var mySecretIdentity = "Jerry O'Connell";
return {
submit : function () {},
clear : function () {},
validate : function () {}
};
}());
And now anything private can only be directly-accessed by the functions which were written inside of the closure.
So again, it comes down to: "What problem are you trying to solve?"
The <script> tag order is important as #Sime Vidas mentioned.
Do the following order:
<script src="hutber.js"></script>
<script src="hutber.form.js"></script>
I modified the script in jsFiddle. You'll note that I like being explicit about global variables by using window.variable. I have the init function in the core hutber.js file firing immediately, if that's what you want.
//core hutber.js
window.hutber = {}; // Explicit Global Variable
(function ($) {
"use strict"; //For good development standards :)
window.hutber.init = function(){
alert('init fired');
};
window.hutber.init(); // You can fire this anywhere since you set it on a global variable...
})(jQuery);
//Extra bits hutber.form.js
(function ($) {
"use strict"; //For good development standards :)
window.hutber.form = {prop: "hello im a form"}
alert('window.hutber.form is now' + window.hutber.form.prop);
})(jQuery);

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.

Enclosing external jQuery script

I have an external JavaScript file that will be used on pages with lots of other scripts. My script involves a lot of jQuery that listens for events, and by design, I have many global vars declared. I've been reading best practice articles, and a lot is said about 'polluting the global namespace' and inadvertent script interaction.
What's the best way to enclose (encapsulate?) my JavaScript file so that:
I can still access some of the
variables outside of the enclosure
The jQuery event listeners will
function properly
I'm not at liberty to disclose the code, so even general responses are appreciated. Additionally, any other tips on making scripts less vulnerable to other scripts on the page are welcome.
I've found enclosure styles for regular JavaScript, but does the use of jQuery complicate this?
Generally what this boils down to is encapsulating your objects into a "namespace". I use quotes there because the term is not an official semantic in JavaScript, but rather one that is achieved through basic object encapsulation.
There are several ways to do this, and it ultimately comes down to personal preference.
One approach is to just use a basic JS object, and keep everything in it. The name of the object should be semantic and give the object some meaning, but otherwise it's purpose is to just wrap your own code and keep it out of the global namespace.
var SomeName = {
alpha: 1,
beta: {a: 1, b: 2},
gamma: function(){
SomeName.alpha += 1;
}
}
In this case, only SomeName is in the global namespace. The one downside to this approach is that everything inside the namespace is public, and you have to use the full namespace to reference an object, instead of using 'this' - e.g. in SomeName.gamma we have to use SomeName.alpha to reference the contents of alpha.
Another approach is to make your namespace a function with properties. The nice feature of this approach is you can create 'private' variable through closures. It also gives you access to closured functions and variables without full namespace referencing.
var SomeName = (function(){
var self = this;
var privateVar = 1;
var privateFunc = function() { };
this.publicVar = 2;
this.publicFunc = function(){
console.log(privateVar);
console.log(this.publicVar); // if called via SomeName.publicFunc
setTimeout(function(){
console.log(self.publicVar);
console.log(privateVar);
}, 1000);
};
}();
The other bonus of this approach is it lets you protect the global variables you want to use. For example, if you use jQuery, AND another library that creates a $ variable, you can always insure you are referencing jQuery when using $ by this approach:
var SomeName = (function($){
console.log($('div'));
})(jQuery);
One method is to namespace like this:
var MyNamespace = {
doSomething: function() {},
reactToEvent: function() {},
counter: 0
}
You will just have to refer to the functions or variable using the namespace: MyNamespace.reactToEvent. This works fine for separating what you would normally have in the window (where all the confrontation is).
You can wrap your code in an anonymous Javascript function and only return what you want to expose to the outside world. You will need to prefix var to your global variables so that they remain only in the scope of the anonymous function. Something like this:
var myStuff = (function() {
var globalVar1;
var globalVar2;
var privateVar1;
function myFunction() {
...
}
function myPrivateFunction() {
...
}
return {
var1: globalVar1,
var2: globalVar2,
myFunction: myFunction
};
})();
Now you can access myStuff.var1 and myStuff.myFunction().
Two ways to encapsulate or limit namespace pollution
1) Create one global var and stuff everything you need into it.
var g = {};
g.somevar = "val";
g.someothervar = "val2";
g.method1 = function()
{
// muck with somevar
g.somevar = "something else";
};
2) For inline scripts, consider limiting the scope of the functions called.
<script>
(
function(window)
{
// do stuff with g.somevar
if(g.somevar=="secret base")
g.docrazystuff();
}
)(); // call function(window) then allow function(window) to be GC'd as it's out of scope now
</script>
I just started using RequireJS and have now become obsessed with it.
It's basically a dependency management system in a modular JavaScript format. By doing so you can virtually eliminate attaching anything to the global namespace.
What's nice is that you only reference one script on your page require.js then tell it what script to run first. From there it is all magic...
Here's an example implementation script:
require([
//dependencies
'lib/jquery-1.6.1'
], function($) {
//You'll get access to jQuery locally rather than globally via $
});
Read through the RequireJS API and see if this is right for you. I'm writing all my scripts like this now. It's great because at the top of each script you know exactly what you dependencies are similar to server-side languages - Java or C#.
This is a common practice with jQuery plugins for the same reasons you mention:
;(function ($) {
/* ... your code comes here ... */
})(jQuery);
This is an immediate function. If you declare your "global" variables inside, they will be local to this closure (still "global" for the code you create inside). Your event listeners will work inside here too, and you will still be able to reach real global variables.

Categories

Resources