I have a fairly large script that contains about 60 global variables. I'm thinking about using the namespace pattern to encapsulate my script and have only one global variable that references one object.
Even though this pattern is considered best practice, I'm also thinking about an alternative: storing the global variables inside the DOM, in hidden divs, and accessing them with $('#MyGlobalVar1').text(). Is this a good idea or not?
Thanks for your suggestions.
No, this is not a good idea.
It pollutes the DOM with non-semantic data, and is less efficient as well. That's even worse than polluting the global JS namespace, and worse still, it only allows you to store strings.
Even if I would recommend you to use a namespace object to hold and reference your data, you can simply put an outer self-invoking function around your code to prevent clobbering the global object.
So you go from
var global1 = true,
global2 = true;
into
(function() {
var global1 = true,
global2 = true;
// rest of all app logic
}());
Beyond that, since you're using jQuery you also might to use jQuerys .data() method. It's designed to reference data for a specific node, but it's internally stored into an ECMAscript object also.
Related
I was looking for this but could not find a question as simple as I want it. The problem is really simple: In angular js, should I use local variables, or properties of this (in cases when I don't need to use this).
Example:
// I need "this" here because I need this collection in template
this.collection = SomeService.fetchCollection();
// I can use either "foo" or "this.foo" here, which one is better?
this.fetchSomeData = function(type) {
var foo = AnotherService.foo(type);
return FooService.call(foo);
}
A local variable, so it can be cleaned up as soon as the method exits. Otherwise it would stay unused in the parent's namespace.
But in 99% of cases that will have no real-world effect, so it doesn't matter.
Because you haven't declared 'foo' as a var it will be a global here, which is bad. You should at least prefix it with 'var' so it's scoped to the function and not globally; it shouldn't be available outside the function.
in my opinion it is a good practice not to reveal everything and keep it encapsulated - for example, it avoids moving logic to view which is bad
also, consider that you have a for loop iteration over i variable - would you also use this.i for such purpose?
I am wondering if it is more or less efficient to encapsulate the main body of your JavaScript code in an object? This way the entire scope of your program would be separated from other scopes like window.
For example, if I had the following code in a JavaScript file:
/* My main code body. */
var somevar1=undefined;
var somevar2=undefined;
var somevarN=undefined;
function somefunction(){};
function initialize(){/* Initializes the program. */};
/* End main code body. */
I could instead encapsulate the main code body in an object:
/* Encapsulating object. */
var application={};
application.somevar1=undefined;
application.somevar2=undefined;
application.somevarN=undefined;
application.somefunction=function(){};
application.initialize=function(){/* Initializes the program. */};
My logic is that since JavaScript searches through all variables in a scope until the right one is found, keeping application specific functions and variables in their own scope would increase efficiency, especially if there were a lot of functions and variables.
My only concern is that this is bad practice or that maybe this would increase the lookup time of variables and functions inside the new "application" scope. If this is bad practice or completely useless, please let me know! Thank you!
I’ve no idea what the performance implications are (I suspect they’re negligible either way, but if you’re really concerned, test it), but it’s very common practice in JavaScript to keep chunks of code in their own scope, rather than having everything in the global scope.
The main benefit is reducing the risk of accidentally overwriting variables in the global scope, and making naming easier (i.e. you have window.application.initialize instead of e.g. window.initialize_application).
Instead of your implementation above, you can use self-calling functions to create an area of scope just for one bit of code. This is known as the module pattern.
This has the added advantage of allowing you to create “private” variables that are only accessible within the module, and so aren’t accessible from other code running in the same global object:
/* Encapsulating object. */
var application=( function () {
var someprivatevar = null// This can't be accessed by code running outside of this function
, someprivatefunction = function () { someprivatevar = someprivatevar || new Date(); };
return {
somevar1: undefined
, somevar2: undefined
, somevarN: undefined
, somefunction: function(){}
, getInitialized: function () { return someprivatevar; }
, initialize: function (){/* Initializes the program. */ someprivatefunction(); }
};
})();
application.initialize();
application.getInitialized();// Will always tell you when application was initialized
I realize you asked a yes or no question. However, my answer is don't worry about it, and to back that up, I want to post a quote from Eloquent Javascript, by Marijn Haverbeke.
The dilemma of speed versus elegance is an interesting one. You can
see it as a kind of continuum between human-friendliness and
machine-friendliness. Almost any program can be made faster by making
it bigger and more convoluted. The programmer must decide on an
appropriate balance....
The basic rule, which has been repeated by many programmers and with
which I wholeheartedly agree, is to not worry about efficiency until
you know for sure that the program is too slow. If it is, find out
which parts are taking up the most time, and start exchanging elegance
for efficiency in those parts.
Having easy to read code is key to my issue here, so I'm going to stick with the modular approach even if there is a slightly longer lookup chain for variables and functions. Either method seems to have pros and cons as it is.
On the one hand, you have the global scope which holds several variables from the start. If you put all of your code right in the global scope, your list of variables in that scope will include your own as well as variables like innerWidth and innerHeight. The list to search through when referencing variables will be longer, but I believe this is such a small amount of overhead it is ridiculous to worry about.
On the other hand, you can add just one object to the global scope which holds all of the variables you want to work with. From inside this scope, you can reference these variables easily and avoid searching through global variables like innerWidth and innerHeight. The con is that when accessing your encapsulated variables from the global scope you would have a longer lookup chain such as: globalscope.customscope.myvar instead of globalscope.myvar or just myvar.
When I look at it this way, it seems like a very trivial question. Perhaps the best way to go about it is to just encapsulate things that go together just for the sake of decluttering code and keep focus on readability rather than having a mess of unreadable code that is only slightly more efficient.
So I know polluting the global namespace referencing the window is a bad thing, especially if you have multiple 3rd party references. So this would be not desirable:
window.someObject = someObject;
That will reference it everywhere. What if I instead use it like this?
var MyApplication = window.MyApplication;
MyApplication.someObject = someObject;
Of course using this approach requires referencing MyApplication = window.MyApplication at the top of each module that needs access to this created namespace. So back to my question. Is this an acceptable approach to giving global access without polluting the window global namespace?
If you want global access, you need to have a global of some sort. This is the common way of doing it.
An example from the jQuery source code:
_jQuery = window.jQuery,
_$ = window.$,
I believe all of the big frameworks do it this way. I'd consider it perfectly acceptable to pollute the global namespace with one container variable.
You can also do (in global context):
(function(lib) {
// in here, lib references window.MyApplication
...
}(MyApplication));
So you can easily change the object passed in.
another question concerning javascricpt closures. I have a global "settings object". Is it better to use it from within functions in global scope or pass the object every time a function needs to access the object?
For a better understanding a little mockup of the situation here
Please ignore that "baz()" also gets the passed object within "foobar()" from the global scope within the closure. You see that both versions work fine.
The thing is that I am passing whatever object the function needs to work to every function and EVERY time (unneccesary overhead?), which might be nice and easy to read/understand but I am seriously thinking about changing this. Disadvantage would be that I have to keep the "this" scope wherever it gets deeper right?
Thanks for your advice!
Your settings object isn't global, it's defined within a closure.
As the intent is that it be accessed by other function within the closure, I'd say you were 100% fine to just access that object directly and not pass it as a parameter.
FWIW, even if you did pass it as a parameter the overhead is negligible because only a reference to the object is passed, not a copy of the whole object.
So you have basically three options:
You want to expose settings as a global variable, and have it accessed by your functions,
You want to hide settings as an implementation detail and have it accessed by your functions,
You want to give a possibility to supply different settings objects to different functions.
Global variable approach
Well, I guess it's a little bit like with any global variable. If settings is a singleton (for example it describes your application) and you can't see any benefit in having a possibility to call the same function with different settings objects, then I don't see why it couldn't be a global variable.
That said, because of all the naming conflicts, in Javascript it's good to "namespace" all the global variables. So instead of global variables foo and bar you should rather have one global variable MyGlobalNamespace which is an objects having attributes: MyGlobalNamespace.foo and MyGlobalNamespace.bar.
Private variable approach
Having a private variable accessed by a closure is a good pattern for hiding implementation details. If the settings object is something you don't want to expose as an API, this is probably the right choice.
Additional function parameter approach
Basically if you see a gain in having a possibility of supplying different settings to different function calls. Or perhaps if you can picture such gain in the future. Obvious choice if you have many instances of settings in your application.
EDIT
As to the question from the comments:
Example 1)
var blah = 123;
function fizbuzz() {
console.log(blah); // <-- This is an example of a closure accessing
// a variable
console.log(this.blah); // <-- Most likely makes no sense. It might work,
// because by default this will be set to a global
// object named window, but this is probably not
// what you want. In other situations this might
// point to another object.
}
Example 2)
var obj = {
blah: 123,
fizbuzz: function() {
console.log(this.blah); // <-- This is *NOT* an example of a closure
// accessing a private variable. It's rather the
// closest Javascript can get to accessing an
// instance variable by a method, though this
// terminology shouldn't be used.
console.log(blah); // <-- This MAKES NO SENSE, there is no variable blah
// accessible from here.
}
};
In a nutshell, I'd encourage you to read some good book on the fundamental concepts of Javascript. It has its paculiarities and it's good to know them.
I have a number of aspx pages (50+).
I need to declare a number(5-7) of global variables in each of these pages.
Variables in one page independent of the other pages even though some might be same.
Currently I am declaring at the page top and outside of any function.
Should I approach this differently and is there any side effects of this approach?
If exact duplicate, please let me know.
Thanks
It is best practice to not clutter the global scope. Especially since other frameworks or drop-in scripts can pollute or overwrite your vars.
Create a namespace for yourself
https://www.geeksforgeeks.org/javascript-namespace/
More here: https://stackoverflow.com/search?q=namespace+javascript+global
Some examples using different methods of setting the vars
myOwnNS = {}; // or window.myOwnNS
myOwnNS.counter = 0;
myOwnNS["page1"] = { "specificForPage1":"This is page 1"}
myOwnNS.page2 = { "specificForPage2":"This is page 2", "pagenumber":2}
myOwnNS.whatPageAmIOn = function { return location.href.substring(location.href.lastIndexOf('page')+4)}
As #mplungjan says, best practice is to avoid global variables as much as possible.
Since window is global, you can declare a namespace at any time and within any function by using window.NAMESPACE = {};
Then you can access NAMESPACE globally and set your values on it as properties, from within the same or another function:
NAMESPACE = { var1:"value", var2:"value" /* etc */ };
If you can do all this within script files rather than directly in your page then so much the better, however I guess you may not have the values available in a static script.
One approach would be to declare the variable on "root" level, i.e, outside any code blocks before any other JS code tries to access it.
You can set global variables using window.variablename = value; in order to keep it clean superficially atleast.