I have a JavaScript global Array, which I'm using in multiple functions. I heard that using global variables will give some performance headache. So, can anyone suggest me how I can avoid using global variable in this case?
var tpaArray = new Array();
In multiple functions, I am using and popping value from it.
[Note] In my code I am actually using multiple global variable and arrays
Global variables are not a performance problem. The problem with globals is that the global namespace is already very, very crowded, and so dumping your symbols there leads to the possibility of conflicting with something else.
It's almost always possible to avoid having globals. The usual way is to wrap all of your code in a scoping function:
(function() {
// Your code here
})();
Then you can have nested functions inside that function, and "globals" within that function that they all share.
(function() {
var someVar;
function foo() {
// You can use `someVar` here
}
function bar() {
// And also here
}
foo();
})();
That said, it's best to avoid having lots of shared variables or near globals, as it makes for writing functions with side-effects, which can be difficult to maintain.
If you have lots of variables, you can put them all into an object and pass this as an argument to each function. Then instead of accessing tpaArray, you'd access data.tpaArray, where data is the name of the argument.
Related
var variableOne;
var variableTwo;
var variableThree;
function veryInterestingFunction() {
var variableFour;
if(a){
variableFour = 'Good';
}
else {
variableFour = 'Decent';
}
console.log(variableFour);
}
$(window).on('scroll', function(){
veryInterestingFunction();
});
Here I have some variables in the global scope, a function declaring a variable and assigning a value to it, and calling this function on scroll.
This way on every scroll you are going to declare the "variableFour" which is not a good practice, right?
However I don't want to crowd the global scope with unnecessary variables and also can't use an IIFE. Is there a "best practice" way to declare the variable outside the function and still only possible to use it inside the scope of that function ?
http://jsfiddle.net/2jyddwwx/1/
to declare the variable outside the function and still only possible to use it inside the scope of that function ?
I guess, that's impossible
When I don't want to crowd the global scope, I will declare one global object, for example App = {}, and instead of global variables, I use it's properties.
App.variableOne;
App.variableTwo;
App.variableThree;
Or you can use classes in ES6
I don't think there's anything wrong with your code sample, I seriously doubt variable declaration is ever going to slow down your code. I'd definitely only start to worry about this kind of thing when you're absolutely certain it's causing issues (it won't), otherwise it might be wasted effort.
If you really want to optimize this, one thing you might be able to do is debouncing the veryInterestingFunction calls - that is if you don't necessarily need to respond to every single scroll event (depends on your logic).
As per your question, IIFE/function closure is essentially the only way to limit scope in JavaScript that I know of, so if you can't use that, I don't see any other option.
There is no problem in declaring an empty variable into your scope. If it is not global, it belongs to the scope.
And there is no need to fear for performance. If you declare variables within your scope, the Javascript garbage collector will empty that for you. Take a read at this article
I've got a problem of having code variable names conflicting each other, ie;
<script type="text/javascript">var a = "hello"; </script>
<script type="text/javascript">alert(a);//this works, when I want 'a' not to exist </script>
Are closures the only option?
Coming from a c# background, its like constructing an unreferenced instance of a delegate, then calling it inline, which seems a bit messy
(function(){var a = "hello";})();
(function(){alert(a);})();//yes! working as expected
Using a (immediately self-executing) function to create a new scope is indeed the way to go.
This also has the advantage that you can ensure that certain variables have certain values. When using jQuery, the following is common for example:
(function($, window, undefined) {
// ...
})(jQuery, this);
Unless you have tons of functions with only a single statement in each (like in your example) it is also perfectly readable.
Yes, closures are your only option. In browsers all JavaScript files get put into the same global scope.
IIFE's are very common place in JavaScript; I wouldnt' call them messy.
Javascript only has function scope, unlike C# which has block scope. The following code is valid javascript and C#:
var x = 2;
while(true) {
var y = 3;
break;
}
//y is not accessible here in C#, but is in javascript
The only way to create a new scope is to create and execute an anonymous function.
For short, inline stuff then you're best to use the module pattern to create a closure and therefore emulate private variables.
(function(){
var a....
})();
A better long-term approach is to use objects as namespaces.
var NS = {};
NS.a = 1;
Just to provide a different perspective. It is possible to write code without using closures, and maintain (arguably) safe global variable scope.
Define a single object, to use as a namespace, with a suitably unique name (e.g. MyAppContext) that will have global scope, and if you need to define global-like variables only for use in your application only, attach them to this object.
MyAppContext.appTitle = 'Application Title';
At the start of your script where you create MyAppContect make sure it doesn't aleady exist.
Make sure that all of your function-scoped variables use the var keyword so you know you're not referencing a global value.
Obviously this approach opens up a risk that you forget to define some of your function variables with var. JSLint can help you in respoect of this this.
I am happy to retract this answer if I start getting flamed, but I believe it is a workable alternative approach to using closures. And hey! it's old skool
I also agree that the use of closures is safer, but thought this might interest you.
So I have a rather large object orientated javascript class, with about 120 functions (a lot of getters and setters). Some of these functions have variables that are basically constants.
What I'm wondering, is should I declare these variables in a global scope of the object, so every time the function is run it doesn't have to re-declare the variable?
An example function is below. this.displayContacts is run several times (and will always run within the object), so in this case, there's no point declaring the 'codes' object inside the function?
function orderObject() {
this.displayContacts = function() {
var codes = {'02':'02','03':'03','07':'07','08':'08'};
// do something with codes
};
}
So, would this be better, performance wise?
function orderObject() {
var codes = {'02':'02','03':'03','07':'07','08':'08'};
this.displayContacts = function() {
// do something with codes.
};
}
My other concern is that if I end up with a lot of global variables/objects inside the main orderObject, will that be MORE of a performance hit than simply re-declaring the variables each time?
absolutely.
function MyClass() {
this.somevar = ''; // instance scoped variable
};
MyClass.CODES = {'02':'02'...}; // 'Class' scoped variable; one instance for all objects
MyClass.prototype.instanceMethod = function(){
// 'this' refers to the object *instance*
// it can still use MyClass.CODES, but can also account for variables local to the class
}
CONSTANT is 'static' so to speak, in java-talk. If your codes are global to the class (and the rest of your application), you will save a lot of overhead this way -- only define the object once. Note that you can have 'static' class-level methods as well, for those cases where the function doesn't need to operate on variables specific to an instance of the class.
Unless your app is really beefy, performance optimization probably wont make it noticeably faster. But that doesn't mean that OO design is not worth-while -- if you are going to use javascript in an object oriented way, its not too hard and never a bad idea to use good OO principals.
I would say that if you have something that you are using in multiple places that it should become a property of your object so that it doesn't have to be redeclared each time. It would also help make the maintenance of the object easier if that constant has to change. Then you are changing it only in one place and not having to hunt down all the locations where you used it.
Don't repeat yourself.
Garbage collection in JavaScript depends on the browser, and most modern browsers handle it pretty well. If you go ahead and make these global, you might see a slight performance increase simply because it's not executing that line of code every time. However, I can't imagine any significant increase in performance by making these static properties on the class, but if they don't change, then it would make more sense.
My intuition is that it's a good idea to encapsulate blocks of code in anonymous functions like this:
(function() {
var aVar;
aVar.func = function() { alert('ronk'); };
aVar.mem = 5;
})();
Because I'm not going to need aVar again, so I assume that the garbage collector will then delete aVar when it goes out of scope. Is this right? Or are interpreters smart enough to see that I don't use the variable again and clean it up immediately? Are there any reasons such as style or readability that I should not use anonymous functions this way?
Also, if I name the function, like this:
var operations = function() {
var aVar;
aVar.func = function() { alert('ronk'); };
aVar.mem = 5;
};
operations();
does operations then necessarily stick around until it goes out of scope? Or can the interpreter immediately tell when it's no longer needed?
A Better Example
I'd also like to clarify that I'm not necessarily talking about global scope. Consider a block that looks like
(function() {
var date = new Date(); // I want to keep this around indefinitely
// And even thought date is private, it will be accessible via this HTML node
// to other scripts.
document.getElementById('someNode').date = date;
// This function is private
function someFunction() {
var someFuncMember;
}
// I can still call this because I named it. someFunction remains available.
// It has a someFuncMember that is instantiated whenever someFunction is
// called, but then goes out of scope and is deleted.
someFunction();
// This function is anonymous, and its members should go out of scope and be
// deleted
(function() {
var member;
})(); // member is immediately deleted
// ...and the function is also deleted, right? Because I never assigned it to a
// variable. So for performance, this is preferrable to the someFunction
// example as long as I don't need to call the code again.
})();
Are my assumptions and conclusions in there correct? Whenever I'm not going to reuse a block, I should not only encapsulate it in a function, but encapsulate it in an anonymous function so that the function has no references and is deleted after it's called, right?
You're right that sticking variables inside an anonymous function is a good practice to avoid cluttering up the global object.
To answer your latter two questions: It's completely impossible for the interpreter to know that an object won't be used again as long as there's a globally visible reference to it. For all the interpreter knows, you could eval some code that depends on window['aVar'] or window['operation'] at any moment.
Essentially, remember two things:
As long as an object is around, none of its slots will be magically freed without your say-so.
Variables declared in the global context are slots of the global object (window in client-side Javascript).
Combined, these mean that objects in global variables last for the lifetime of your script (unless the variable is reassigned). This is why we declare anonymous functions — the variables get a new context object that disappears as soon as the function finishes execution. In addition to the efficiency wins, it also reduces the chance of name collisions.
Your second example (with the inner anonymous function) might be a little overzealous, though. I wouldn't worry about "helping the garbage collector" there — GC probably isn't going to run in the middle that function anyway. Worry about things that will be kept around persistently, not just slightly longer than they otherwise would be. These self-executing anonymous functions are basically modules of code that naturally belong together, so a good guide is to think about whether that describes what you're doing.
There are reasons to use anonymous functions inside anonymous functions, though. For example, in this case:
(function () {
var bfa = new Array(24 * 1024*1024);
var calculation = calculationFor(bfa);
$('.resultShowButton').click( function () {
var text = "Result is " + eval(calculation);
alert(text);
} );
})();
This results in that gigantic array being captured by the click callback so that it never goes away. You could avoid this by quarantining the array inside its own function.
Anything that you add to the global scope will stay there until the page is unloaded (unless you specifically remove it).
It's generally a good idea to put variables and function that belong together either in a local scope or in an object, so that they add as little as possible to the global namespace. That way it's a lot easier to reuse code, as you can combine different scripts in a page with minimal risks for naming collisions.
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.