Basic Javascript Function - javascript

I am trying to learn more about Javascript, I have been coding with PHP and making web application for years, I have basic knowledge of JS, most of the JS I have used has been already coded and me just plugging it in until recently, in the past years I have been able to do a lot with jQuery.
I have noticed that Stack Overflow uses jQuery more then most sites I have seen, it is beautiful all the JS functionality they have here.
So a basic question, Stack Overflow uses StackExchange in front of most of the JS code that I have seen on here. What exactly is that doing? To me I would want to say it is like a Class name but I read JS does not have classes.
Here is an example code
StackExchange.debug.log("no cache breaker for " + q);
Can you break this down for me to explain what the StackExchange, debug, log are?
I mean I can tell that log must be a function call but the others?
PS) Please don't move this to META as it is a JS question and not specific to StackOverflow
Also feel free to edit the question title and delete this line if you can think of a better title, thanks

Think of StackExchange as something much like the global jQuery function, "$" (or "jQuery"). It's just a global reference to an object that has functions and other properties.
Thus, "debug" is a property of the global "StackExchange" object, and in turn "log" is a property of the "debug" object. In this case, the "log" property references a function, which clearly is a debugging tool.
It's a debatable point whether JavaScript has "classes" or not, but it definitely has objects. (By "debatable" I mean it's a subject that fills an endless stream of blog posts and Stackoverflow questions :-)
That is, in fact, basic JavaScript. There's nothing super fancy or tricky about it.

Namespaces.
this may be relevant
How do I declare a namespace in JavaScript?

EDITED FOR CLARIFICATION
Before I say ANYTHING, please see How Classical Object-Oriented Programming Translates to Javascript. This is VERY important to understand. Now, that being said, I'll continue :)
Javascript has the unfortunate characteristic that you have to understand the run-time environment very well in order to make sense of why certain syntax is chosen over another that expresses the same thing (in theory). One of the main caveats of the run-time environment of javascript is that it is very easy to get things into the global space unintentionally. Here's two quick examples (these examples assume that you don't have any other code written):
/*
* Example 1
* This example uses 'object literal notation'.
* A link to an article about this is below the example.
* This example shows how easy it is to get into the global space just by
* not declaring variables properly.
*/
var myObj = {
myMethod: function() {
test = 'test'; // oops! now the variable test is in the global
// function space :(
// to avoid this, use var test = 'test'; to keep
// test in the scope of myMethod
}
};
Read about object literal notation.
/*
* Example 2
* This example shows how the infamous 'this' can be misused to accidentally
* get into the global space.
*/
var myConstructor = function() {
this.test = 'test';
};
var myObj1 = new myConstructor(); // 'this' will by 'myObj1'
var myObj2 = myConstructor(); // 'this' will by the global object :(
To see why Example 2 is true, see this.
One of the ways you avoid all of these headaches is by following good patterns that control access to the global scope. As some of the answers have pointed out, you can think of the StackExchange object as being used for namespacing purposes, but in reality, it's most often used to also avoid the problem listed in above example, as well prevent things such as name hoisting. In addition, you can make this 'namespacing' object also behave more like a traditional object from other classical OOP languages if you are intelligent in using closure scopes (taking advantage of the fact that all scopes in javascript are bound to functions, and functions in javascript are first-class data objects). Also, because the global space is so dangerous, it's best to "be a good DOM citizen" and only create one object in the global space that encapsulates all of your logic and data.
Joel and jeff are probably actually setting up closure scopes to do information hiding the javascript way. The below is just an example:
StackExchange = (function() { // give StackExchange it's own scope to prevent
// name hoisting and also to allow for private
// data
var version = '1.0.0'; // version only seen inside function scope
return { // return an object that will become 'StackExchange' and whose
// methods have access to this function's scope (closure)
debug: (function() {
// set up logging function that will be determined based on
// 'someCondition' (not defined in this code)
var loggingFn = (someCondition) : console.log ? alert;
return { // return obj with access to this function scope
log: function(strToLog) {
loggingFn.call(this, strToLog);
}
};
})(), // immediately execute to make object with 'debug' scope access
getVersion: function() {
return version; // this function has access to StackExchange
// scope; therefore, version will be available
}
};
})(); // immediately execute to make object with 'StackExchange' scope access
For more information, see name hoisting and scoping. Also, please read about Prototypical Inheritance in Javascript to understand patterns used to avoid global scoping problems.

This code would define the object necessary to perform the call shown in your example. As you can see, it simply defines an object containing more objects finally containing one or more functions.
var StackExchange = {
debug: {
log: function(whatever) { /* some code */ }
}
};
StackExchange.debug.log("no cache breaker for " + q);

StackExchange is a global object and debug is an another object which is a property of StackExchange object and it has a function called log.
Read more about Objects in JavaScript here.

Related

Can we change the execution context of the browser's JavaScript from Window object to something else?

Assume I have a legacy file called module.js which is like this:
a=1;
This by default attaches to the window object polluting the global (actually window) scope when you execute it in the browser.
Is it possible for me to attach it to a different object instead without changing the contents of the source code?
Since the only real problem is the execution context and nothing else, an ideal solution would be something like this:
change execution context from window to module object;
execute the code;
change execution context from module to window object;
If this is not possible, adding wrappers (like IIFE) to the source code is fine as long as the inner contents are not changed. Changing the inner contents needs a full scan of the code which is expensive.
I can, for example, wrap it into a function like this (✓):
function module()
{
a=1;
}
If it is executed in strict mode, I can avoid global scope pollution. However, I can't get hold of the object.
I don't want to do something like this (✗):
module = function module()
{
return a=1;
}
because we need to add return wherever there is an assignment and that means scanning the entire code.
I am just trying to see ways to improve legacy code meant for the browser with minimal effort.
The answer to the first question, no it is not possible to change the default execution context in the browser. window is a special variable and assigning anything else to it will not change default execution context. See Global Object in MDN. And here is an illustration
(function() {
window = {}
a = 5 // leaking declaration
var b = 10
})()
console.log(a) // a is on global scope
//console.log(b) // exception b is not defined in this scope
var b = 5
window = new Object()
window.c = 5
console.log(window.b) // 5
console.log(c) // 5
The answer to the second part about how to work with legacy code, there are many tools which do AST transformation and depending on your goal you should probably use one or more of them.
jscodeshift allows you to write codemods which are functions that receive code and apply transformations to it. This is probably the most powerful tool in this category.
ESLint allows you to set rules (for example no global vars) and have a --fix option which will apply automatic fixes in some cases like changing from single quote to double quotes (this is mostly for style related rules).
prettier is a code formatter only concerned with code appearance: indentation, spaces etc.
AST Explorer an online tool that lets you see the internals of all the above tools very useful to understand how it works and try code on small examples.

Need advise/help on getting rid of global variables

Yes, this is another topic about global variables. I've searched quite a bit about them. But most of the topics is just about WHY not to use global variables and I'm convinced that I shouldn't, and I am more wondering HOW not to use them, and that I'm still unsure about.
I am working on a project, and it works wonders, but I am using about 50 global variables at the moment and that number keeps rising. Right now I've split things up in multiple .js files. Like load_chunks.js, load_images.js, render_map.js, player_actions.js, input.js, to spread the functions based on what they are for. And I've put all global variables inside settings.js.
Currently I use these global variables for these reasons:
1. Calculation based on some other global variables that doesn't change much or at all after loading. By doing this once, and store it in a global variable, I no longer have to repeat the calculation ever again. If I didn't store it in a (global) variable, Javascript would have to do the calculation many times each second, in some cases even up to few thousand times per second.
2. When the global variable is needed in many functions. Like there's this World-variable, that I use to hold data for the appearance of the world. This variable is a multidimensional array. World[y][x] for example. Load_chunks.js adds more data to this variable, or remove data if you move too far. This variable is also needed in render_map.js, to create the map, and it's also needed in player_action.js, to see if you can step on that particular location.
3. Settings; So a number in a variable that remains the same unless I change them in my script. Instead of going through my scripts, and change the numbers manually after a long search and thinking what the number was, I've put that number in 1 variable and call that variable numerous times in my scripts. These variables are in some cases also needed elsewhere.
Also I like to mention that I don't use classes, and perhaps for that reason I never got around using global variables...?
So how do I get rid of my global variables, or shouldn't I?
I hope you can show me or write for me a script example (or a link to it) of how I should do it. That's the fastest way I learn.
Put Variables Inside a Function Closure
One common way to eliminate a global is to put is inside a function closure:
(function() {
var declareYourFormerGlobalHere = 0;
// put all code that uses the variable inside this closure
// the variable persists for this code to use, but is not actually global
})();
Here's are some usage examples:
// example keeping track of a running count and a cached DOM element
(function() {
var cntr = 0, obj = document.getElementById("test");
setInterval(function() {
++cntr;
if (obj.value < cntr) {
// do something
} else {
// do something else
}
}, 1000);
})();
// example keeping track of a time of last click
(function() {
var timeOfLastClick = 0;
document.getElementById("run").addEventListener("click", function(e) {
var now = new Date().getTime();
// only process click if more than 2 seconds have passed since last click
if (now - timeOfLastClick > 2000) {
// OK to process the click
}
timeOfLastClick = now;
});
})();
Sometimes, you can actually enclose all your code or nearly all your code in a single closure like this and all your current globals become local variables inside the closure rather than actual globals. jQuery uses this technique to declare lots of persistent variables it uses, none of which are actual globally scoped.
Use a Single Namespace Object
Another common method of reducing the number of globals is to use the namespace concept. In this concept, you declare a single global object and put other persistent variables as properties of this single global object. This still leaves you with a single global variable, you can have as many properties as you want off this single global.
var myNamepaceObject = {};
myNamespaceObject.var1 = "foo";
myNamespaceObject.var2 = "whatever";
This technique is also used by jQuery as all globally accessible functions that jQuery offers are available off the jQuery object such as jQuery.extend() or jQuery.contains(). jQuery exposes a single global variable and many other globally accessible functions are then available as properties of that single global object.
Module Pattern
What is commonly known as the "module pattern" uses a combination of these above two techniques, where you have a single module variable that both uses properties and closure variables.
var MODULE = (function () {
var my = {},
privateVariable = 1;
function privateMethod() {
// ...
}
my.moduleProperty = 1;
my.moduleMethod = function () {
// ...
};
return my;
}());
You can see a discussion of this design pattern in these references:
JavaScript Module Pattern: In-Depth
Learning Javascript - The Module Pattern
Mastering the Module Pattern
JavaScript module pattern with example
I'm convinced that I shouldn't, and I am more wondering HOW not to use them, and that I'm still unsure about.
load_chunks.js, load_images.js, render_map.js, player_actions.js, input.js, strongly hint to a procedural implementation, that is your architecture probably has several functional pieces and you pass data around between these functions. That's where your global variables are coming from.
So how do I get rid of my global variables (...)
To change that, you need to structure your system in an object or component based approach, that is:
encapsulate data + respective functions by objects in your problem domain, e.g. have a World object that contains Avatar, Buildings, Airborne objects etc. (or whatever your project is about).
separate the problem domain's logic from view logic (e.g. use a MVC architecture)
then your project organises the interactions between view and model objects by essentially exchanging messages between them.
To facilitate this, I suggest these fine frameworks, or some equivalents suitable for your run-time environment:
requirejs - to encapsulate modules into globally managed components
backbonejs - to have an efficient, proven model/view, class/object model (actually built for use with a REST-style backend, but that's not a strict requirement)
Code structure
Typically, I structure my applications such that there is one .js file per each object component/module. A module in this sense contains both the class definition and the corresponding collection. The modules are managed by requirejs and the class definitions are done using backbonejs.
I hope you can show me or write for me a script example
/* define a class e.g. in someclass.js */
define(['backbone'], function($B) {
var SomeClass = $B.Model.extend({
// all instance variables, methods etc. follow
someVar : value,
someMethod : function() { ... },
});
return SomeClass;
});
/* use the class, e.g. in app.js */
require(['someclass'], function(SomeClass) {
var instance = new SomeClass({ initial model attributes });
var value = instance.get('attribute');
instance.someMethod();
...
});
i had the same problem before but it was a big problem as we had a third party javascript code and our code live in clients websites so we should find a way to omit the appearance of global variable so to be short:
Use 1 global variable namespace and make all other to be properities for it:
GlobalVariable = {}
GlobalVariable.var1 = "var1"
GlobalVariable.var2 = "var2"
You can also make it more useful and divide it into groups:
GlobalVariable.helper = {}
GlobalVariable.helper.var1 = "var1"
GlobalVariable.helper.var2 = "var2"
so you can use same names under different groups.
and if you want to Omit it totally you can use:
(function(document, window) {
// all variables here is global only inside the scope
}(document, window));

How do I prevent accidental global name space pollution with javascript eval?

I am writing a simple REPL (Read, Evaluate, Print, Loop) implementation in JavaScript. I am able to isolate code and calling context like so:
var sandbox = {
// Allow the input code to use predefined helper functions
// without the preceding use of the this keyword.
helper_fn: function() { alert("foo"); }
};
var func = new Function("with (this) { " + user_inputed_code + " }");
func.call(sandbox);
Now it closes the user_inputed_code so that this referers to sandbox and if the inputted code accesses or mutates this it is affecting sandbox.
However, I noticed that if the imputed code were to accidentally forget to preface a variable assignment with the keyword var that the global namespace get polluted.
Is there anyway to prevent this? If so how (maybe a regexp?)? Is there a better way to approach this?
I'm going to provide two completely different approaches from what others discussed here. They are both drastic, and are useful when you want to relatively isolate your environment.
The easiest technique that works in all browsers is to probably create an iframe, and append script tags to it. (Note, a really overzealous iframe can still get past that if they're in the same domain, at least in older browsers). I discuss that in this question.
Use web Workers, which have an isolated environment by default and have no access to the global object of the main execution thread. I discuss that in this question.
More specifically, if you're building a REPL take a look at this answer where we discuss and I explain how to eval code in the same scope but outside the global scope, using the first approach of iframes.
(I assumed a browser, in node you can simple use the vm module and select the context in runInContext)
Turns out there is a way with "use strict" and without Object.freeze. You have to manually replace the global namespace with your own sandbox object:
var sandbox, module, func, output;
// Empty object or with defined methods / properties
// you want to expose as globals.
sandbox = {};
// A reference to an object you WANT to provide safe
// access to. In this example it's just an empty object.
module = {};
// A better version of eval:
func = new Function("module", "with(this){return(function(module,global,window){\"use strict\";return eval(\"" + code + "\");})(module,this,this)}");
output = func.call(sandbox, module);
This code allows global and window to refer to a sandboxed object instead of the global name space. It masquerades the variables global and window as the sandbox object and the use of "use strict" will cause it to throw an exception if the input missed the use of var. It also wraps the function in a with statement to make the methods and properties defined in the sandbox object to work as if they were preceded by this.. To see an implementation example (with test specs) check out this gist.
Thank you all for your ideas. Hope this answer helps others.

What advantages does using (function(window, document, undefined) { ... })(window, document) confer? [duplicate]

This question already has answers here:
How does this JavaScript/jQuery syntax work: (function( window, undefined ) { })(window)?
(5 answers)
Closed 8 years ago.
I guess using this pattern is the new hotness, but I don't understand what the advantage is and I don't understand the scoping implications.
The pattern:
(function(window, document, undefined){
window.MyObject = {
methodA: function() { ... },
methodB: function() { ... }
};
})(window, document)
So I have several questions about this.
Is there a particular advantage to encapsulating an object like this?
Why are window and document being fed in instead of just being accessed normally?
Why the heck is undefined being passed in?
Is attaching the object we're creating directly to window a particularly good idea?
I'm used to what I'll call the Crockford style of Javascript encapsulation (because I got it off the Douglas Crockford Javascript videos).
NameSpace.MyObject = function() {
// Private methods
// These methods are available in the closure
// but are not exposed outside the object we'll be returning.
var methodA = function() { ... };
// Public methods
// We return an object that uses our private functions,
// but only exposes the interface we want to be available.
return {
methodB: function() {
var a = methodA();
},
methodC: function() { ... }
}
// Note that we're executing the function here.
}();
Is one of these patterns functionally better than the other? Is the first one an evolution of the other?
Why are window and document being fed in instead of just being accessed normally?
Generally to fasten the identifier resolution process, having them as local variables can help (although IMO the performance improvements may be negligible).
Passing the global object is also a widely used technique on non-browser environments, where you don't have a window identifier at the global scope, e.g.:
(function (global) {
//..
})(this); // this on the global execution context is
// the global object itself
Why the heck is undefined being passed in?
This is made because the undefined global property in ECMAScript 3, is mutable, meaning that someone could change its value affecting your code, for example:
undefined = true; // mutable
(function (undefined) {
alert(typeof undefined); // "undefined", the local identifier
})(); // <-- no value passed, undefined by default
If you look carefully undefined is actually not being passed (there's no argument on the function call), that's one of the reliable ways to get the undefined value, without using the property window.undefined.
The name undefined in JavaScript doesn't mean anything special, is not a keyword like true, false, etc..., it's just an identifier.
Just for the record, in ECMAScript 5, this property was made non-writable...
Is attaching the object we're creating directly to window a particularly good idea?
It's a common way used to declare global properties when you are on another function scope.
This particular style does bring some benefits over the "Crockford" style. Primarily, passing window and document allows the script to be more efficiently minified. A minifier can rename those parameters to single-character names, saving 5 and 7 bytes respectively per reference. This can add up: jQuery references window 33 times and document 91 times. Minifying each token down to one character saves 802 bytes.
Additionally, you do get an execution speed benefit. When I first read #joekarl's assertion that it provides a performance benefit, I thought, "that seems rather spurious." So I profiled the actual performance with a test page. Referencing window one hundred million times, the local variable reference provides a modest 20% speed increase (4200 ms to 3400ms) in Firefox 3.6 and a shocking 31,000% increase (13 sec to 400ms) in Chrome 9.
Of course, you're never going to reference window 100,000,000 times in practice, and even 10,000 direct references only take 1ms in Chrome, so the actual performance gain here is almost completely negligible.
Why the heck is undefined being passed in?
Because (as mentioned by #CMS) the token undefined is actually undefined. Unlike null, it has no special meaning, and you're free to assign to this identifier like any other variable name. (Note, however, that this is no longer true in ECMAScript 5.)
Is attaching the object we're creating directly to window a particularly good idea?
The window object is the global scope, so that's exactly what you're doing at some point, whether or not you explictly write "window." window.Namespace = {}; and Namespace = {}; are equivalent.
I'm with you in using Crockford's style.
To answer your questions
1.Is there a particular advantage to encapsulating an object like this?
The only advantage I can see is by making window and document local variables instead of global variables, you get some added safety by not being able to directly overwrite either one and also some performance gain by them both being local.
2.Why are window and document being fed in instead of just being accessed normally?
Addressed above. Local variables tend to be faster, but with jit compiling these days thats becoming nominal.
3.Why the heck is undefined being passed in?
No clue....
4.Is attaching the object we're creating directly to window a particularly good idea?
Probably not, but I would still stick with Crockford's pattern as attaching the function to the window object exposes it to the rest of the global stack through the window object as opposed to exposing it through a non-standard namespace.
I think this is mostly for code that needs to run in multiple window contexts. Say you have a complex application with lots of iframes and/or child windows. They all need to run the code in MyObject, but you only want to load it once. So you load it in whatever window/frame you choose, but you create a MyObject for each window/frame with references to the proper window and document.
Taking an undefined argument is trying to protect against the fact that undefined can be changed:
undefined = 3;
alert(undefined);
See CMS's answer about how this improves safety.

I've Heard Global Variables Are Bad, What Alternative Solution Should I Use?

I've read all over the place that global variables are bad and alternatives should be used. In Javascript specifically, what solution should I choose.
I'm thinking of a function, that when fed two arguments (function globalVariables(Variable,Value)) looks if Variable exists in a local array and if it does set it's value to Value, else, Variable and Value are appended. If the function is called without arguments (function globalVariables()) it returns the array. Perhaps if the function is fired with just one argument (function globalVariables(Variable)) it returns the value of Variable in the array.
What do you think? I'd like to hear your alternative solutions and arguments for using global variables.
How you would use globalVariables();
function append(){
globalVariables("variable1","value1"); //globalVariables() would append variable1 to it's local array.
};
function retrieve(){
var localVariable1 = globalVariables("variable1"); //globalVariables() would return "value1".
};
function retrieveAll(){
var localVariable1 = globalVariables(); //globalVariables() would return the globalVariable()'s entire, local [persistently stored between calls] array.
};
function set(){
globalVariables("variable1","value2"); //globalVariables() would set variable1 to "value2".
};
Is this a Singleton Pattern BTW?
In this specific scenario a function may set a variable at one point in time, and much later another function, maybe when a user submits a form, will need to get that variable. Therefore the first function couldn't pass the variable as an argument to the later function as it would never be called from the first.
Thank you, I appreciate all your help!
The primary reason why global variables are discouraged in javascript is because, in javascript all code share a single global namespace, also javascript has implied global variables ie. variables which are not explicitly declared in local scope are automatically added to global namespace. Relying too much on global variables can result in collisions between various scripts on the same page (read Douglas Crockford's articles).
One way to reduce global variables is to use the YUI module pattern. The basic idea is to wrap all your code in a function that returns an object which contains functions that needs to be accessed outside your module and assign the return value to a single global variable.
var FOO = (function() {
var my_var = 10; //shared variable available only inside your module
function bar() { // this function not available outside your module
alert(my_var); // this function can access my_var
}
return {
a_func: function() {
alert(my_var); // this function can access my_var
},
b_func: function() {
alert(my_var); // this function can also access my_var
}
};
})();
now to use functions in your module elsewhere, use FOO.a_func(). This way to resolve global namespace conflicts you only need to change the name of FOO.
Semantics my boy. Semantics.
Start with one global: myApp = {};
Everything should be in that. The only exception would be your AJAX library (there are some extreme exceptions like working with JSONP callbacks).
There should be very few properties in myApp. You'll want to hold your application properties in containers such as config or settings.
myApp = {
config:{
prop:1
},
settings:{
prop:2
},
widgets:{
List: function(props){},
Item: function(props){}
}
}
Then you may have more properties in lower modules, components, singletons and Class constructors (widgets).
This setup gives you the added benefit of being able to access any property from any other location since you can get it with the myApp global. However, you should use "this" whenever possible because the lookup is faster. And just set the property directly, don't bother with the pseudo getter/setter stuff. If you really need a getter/setter, code it for that specific use.
The reason your example doesn't work is it's too generic and you seem to be looking for an excuse to work in the global space.
And don't get clever with private variables. They're bad too:
http://clubajax.org/javascript-private-variables-are-evil/
Global state causes problems in several areas. One is code reuse. When you access some global state that means the component must be aware of it's environment(something outside of itself). You should avoid this as much as possible, because it makes the component unpredictable.
Say I have an object that accesses your globalVariables function and I want to use it in another page. How do I know to define the globalVariables object or even how to define it? However if you can pass the information into a constructor or as an argument to a function then I can easily determine what is required by the object.
Also when you access or modify the global scope then you risk affecting other objects. This is why libraries like jquery use only a single name on the global scope(the least possible). It lessens the possibility of conflict with other libraries. In other words the global scope is out of your control, so it is dangerous.
Using global variables is generaly speaking a bad practice, regardless of the language of choice. They are not even (easily) allowed to use when at strict mode, which I highly recommend.
Consider this piece of code I found:
if (typeof session != 'undefined' && !data.cart.request_status)
data.input_definitions.passengers =
inflate_passenger(session, data.input_definitions.passengers);
I needed to turn around and ask a felow programmer where did this session variable came from, as no code search showed up where was set.
I turned out another package from the company sets the global variable.
Code it's like a joke: if you need to explain it it's probably not that good.
Workaround using ES6:
If at Node, use import or require to bring the desired stuff into lexical scope, don't let people touch your global environment without you knowing it.
import {Sesssion} from 'api-core';
const Session = require('api-core').session;
If you are at the frontend delivering code for the browser you can't use import unless you transpile your ES6 code using Babel.
Example transpiling using Gulp.js:
// $ npm install --save-dev gulp-babel babel-preset-es2015
// gulpfile.js
const gulp = require('gulp');
const babel = require('gulp-babel');
gulp.task('transpile', () => {
return gulp.src('src/app.js')
.pipe(babel({presets: ['es2015']}))
.pipe(gulp.dest('dist'));
});
// $ gulp transpile
Legacy workaround:
When using ES6 features is not an option the only workaround to using a bunch of global variables, is using only one, and have hope:
// scripts/app.js
var MyApp = {
globals: {
foo: "bar",
fizz: "buzz"
}
};
var ASHIVA_HandsOffNHS = (function() {
// VARIABLES
var my_var = 10;
// PRIVATE FUNCTIONS
function bar() {
console.log(my_var + 5);
}
// PUBLIC OBJECT
myObject = {};
myObject['a_func'] = function() {
my_var += 10;
console.log(my_var);
};
myObject['b_func'] = function() {
my_var = 0;
console.log(my_var);
};
return myObject;
})();
ASHIVA_HandsOffNHS.a_func();
ASHIVA_HandsOffNHS.b_func();
ASHIVA_HandsOffNHS.a_func();
The issue with your solution is that it just makes you code harder to understand while still keeping all the downsides of global variables. The page you linked to covers the problems. The only problem your proposed solution really solves is namespace pollution but at the cost of not being able to see what global variables are declared as easily as the declaration is a function call).
The solution is to write code without global variables. If a function needs a value pass it as a argument.
You really don't want to do this.
As to why see e.g. the top post here: What is the most EVIL code you have ever seen in a production enterprise environment?
As a side note, one can always execute "global" code without littering the place with globals:
(function() {
var notaglobal = 1;
alert(notaglobal);
})();
//notaglobal is not defined in this scope
Other answer most explain with anonymous function as this article mention,
Anonymous functions are difficult to debug, maintain, test, or reuse.
Here are example with normal function. It's easier to read and understand.
/* global variable example */
var a= 3, b= 6;
function fwithglobal(){
console.log(a, b); // 3 6 expected
}
fwithglobal(); // first call
function swithglobal(){
var a=9;
console.log(a, b); // not 3 6 but 9 6
}
swithglobal(); // second call
/* global variable alternative(function parameter) */
function altern(){
var a= 3, b= 6; // var keyword needed
f_func(a,b);
s_func(a,b);
}
function f_func(n, m){
console.log(n, m); // 3 6 expected
}
function s_func(n, m){
var a=9;
console.log(n, m); // 3 6 expected
}
altern(); // only once
Global variables are bad... if left unmanaged!
The potential risks of global variables is as high as the pleasure and productivity gains of having frequently used objects ready to use.
I don't believe one should seek a single alternative. Instead I advocate for one object in charge of managing those globals and as the code base/component matures, refactor them out
One thing not mentioned in the current answers which I think is critical is an understanding of DI and IoC containers. These address many of the problems people try to solve with global variables, but covering related concerns that plain globals can't, like object life cycles.

Categories

Resources