jQuery: Global Variable Namespace Problem - javascript

Is there a way to declare a global variable in jQuery in its own namespace?
Sure, I can declare global variables with plain old JavaScript, but they will fall in the window's namespace. For example, if I had a variable named document, it would surely overwrite the document object of the window.
Does jQuery have a hash table that lets you store any object by their name?
Thanks.

Not sure why you want to use jQuery for that? You could just create your own namespace:
var namespace = {
document : "Foo"
};
Please elaborate, if there's some need to use jQuery somehow.

Of course you can. Create a namespace as an object and then attach it to the jQuery function.
(function ($) {
$.myNamespace = {};
})(jQuery);
Here I've created an auto-executing anonymous function to do the work. I can then add other propertes and functions to the namespace inside this function. Also this avoids the problem of someone else renaming $ to something else.
After this is done you can refer to your namespace as jQuery.myNamespace

If the variable is something that want to associate with an element to be used later, maybe in a different routine, you could use jQuery's "data" method to store it.
e.g.
:
:
// Save original HTML content.
var old_html = $('#box').html();
$('#box').data({originalContent: old_html});
// Replace with new content.
$('#box').empty().html(new_html);
:
// Restore original content (maybe in a different function).
var orig_html = $('#box').data('originalContent');
$('#box').empty().html(orig_html);
:
I hope this is useful to you.
Regards
Neil

Related

Can I add attributes to 'window' object in javascript?

Can I add any random attribute to 'window' object in javascript? Some thing like:
window.my_own_attr = "my_value"
Does it have any side effects with any libraries? And is it cross-browser compatible?
Can I add any random attribute to 'window' object in javascript?
Yes, just like you've shown.
Does it have any side effects with any libraries?
No, not unless you use a library which sets a property you then overwrite.
And is it cross-browser compatible?
Yes, completely.
Having said that, this practice is generally frowned upon. You could end up overwriting something you don't want to.
In all browsers, window is the javascript global namespace. Every property or method 'lives' in that namespace. So if you assign a property to window, it is in effect a global variable.
example:
window.myConstant = 5;
// note: a var declaration will be a window property too
// note 2: 'let' or 'const' will not be window properties
// below can also be done without 'var'.
var myConstantGlobal = 4;
console.log(`multiply(10) => ${multiply(10)}`);
console.log(`multiply() => ${multiply()}`);
console.log(`multiplyGlobalVar(10)) => ${multiplyGlobalVar(10)}`);
console.log(`multiplyGlobalVar() => ${multiplyGlobalVar()}`);
function multiply(val){
return myConstant * (val || 1);
}
function multiplyGlobalVar(val){
return window.myConstantGlobal * (val || 1);
}
You have to be cautious with javascript frameworks. For instance, if you declare window.JQuery, and use the JQuery framework, the JQuery namespace will be replaced by your assignment, rendering it useless.
Yes, you can, but in general you shouldn't.
The window object is also the JS default "global" object, so all global variables get added there.
You're unlikely to break anything unless you overwrite a property that's already there, but it's considered bad practise to dump variables on window, or otherwise create lots of global variables.
I won't repeat what others have said re: the hackyness of this practice. But it can be incredibly useful when using a rigid framework like Angular mixed with vanilla HTML / JS (or jQuery) code. Which is also hacky and frowned upon, but sometimes there are good reasons, like if you have lots of pre-existing JS code that will be challenging to integrate into the framework.
The more interesting question to me is HOW to make use of the ability to add properties to the global window object. There is a pattern I use when I want to expose the methods of an Angular provider (service) to code that otherwise would be unable to inject the service, probably because it runs outside of the Angular DI framework. The way I do it is as follows:
Define your service as a provider in your top level module.
In the constructor or onInit of app.component.js (or whatever your top level component is that imports the provider), inject the provider normally, perform any one time initialization that it needs, and then call window['MyServiceName'] = this
Assuming you have designed the provider to follow a Singleton pattern, your provider's methods can now be safely called from anywhere. A non-Angular script need simply call window['MyServiceName'].methodName()
That 'll work fine, no conflict with any library until used same variable name, will work in all browsers, but not recommended as this will create global JS variable.
In IE if an element has an id, then that node is accessible on the window object as a property:
<div id="num"></div>
alert(num); //Element
num = 3; //throws exception
var num = 3; //ok
As pointed out by others yes you can and yes it means adding "global variables".
Having global variables is not best practice but sometimes it is the simplest thing to do. For instance if you use IFrames and want the child-window to access some property of the parent window. Such a property must be "global" for a child to access it. But this also shows that it is not "truly global", it is just a property of a specific window. But it can conflict with other property-names such as names of functions defined in the same window, perhaps by some libraries you use.
So we know global variables are bad. If we decide to use them anyway is there anything we can do to minimize their badness?
Yes there is: Define a SINGLE global variable with a more or less unique name, and store an OBJECT into it. Store all other "variables" you need as fields of that single object.
This way you don't need to ever add more than a single global variable (per window). Not TOO bad.
Name it more or less uniquely so it is unlikely to conflict with anybody else's single global. For instance you could use your name + 's' as the variable name:
window.Panus = {};
:-)

Troubles with (function(){})() [duplicate]

This question already has answers here:
What is the purpose of a self executing function in javascript?
(21 answers)
Closed 8 years ago.
So far I've learned the benefits of using this function (is it wrapping?)
So, it almost acts like namespaces.
Suppose we have:
( function() {
function foo(){
alert(true);
}
foo(); //alerts true
})();
( function() {
function foo(){ //the same title of the function as above
alert("another call of foo");
}
foo(); //alerts, ok.
})();
Also I've noticed it can access public vars, like this:
var __foo__ = 'bar';
( function() {
alert(__foo__); //alerts bar
})();
I have several questions regarding this approach
What I've tried:
Use Bing for tutorials (I' found them, but many of them don't answer my questions)
Play with passing objects into the body
Find the answer here
But, I'm still beating my head against the wall
So the questions are:
I've seen people pass objects as params, but when DOES it make sense?
For example, what does it mean?
( function(window) {
})(document);
I saw smth like this in Jquery UI Lib
( function($) {
//some code of widget goes here
})(Jquery);
This makes inner code visible outside the function, right? (not sure) Why, this is because
we can access the object (say we have "modal" widget), simply by calling it,
like:
$(function(){
$("#some_div").modal(); //here it's object the we got from the function
});
And the second question is: How does it work.
I've seen people pass objects as params, but when DOES it make sense? For example, what does it mean?
( function(window) {
})(document);
The language does not treat parameters to immediately called functions differently than parameters to other functions.
It makes sense to use a parameter whenever you want a local name in your function body for an input. In this case it's a bit confusing since window and document are likely to be confused.
( function($) {
//some code of widget goes here
})(Jquery);
This makes inner code visible outside the function, right? (not sure) Why, this is because we can access the object (say we have "modal" widget), simply by calling it,
No. It does not by itself make any code visible outside the widget. It's just a parameter definition which provides a new&local name for a global variable.
What makes inner code visible outside is attaching it to an external object as in
$.exportedProperty = localVariable;
which is a common convention in jQuery code.
There are mainly 2 purposes of passing in the window and document objects such as seen below
(function(window, document){
// code
}(window, document);
Javascript can access local variables faster than global variables. This pattern in effect makes the names window and document local variables rather than global, thus making your script slightly faster.
Making these names local variables has another benefit: minifiers can rename them. So if you minify the above script, the local version of window might get renamed to a and document might get renamed to b, thus making the minified script smaller. If you were to reference them as globals, these renamings are impossible because that would break your script.
For more info, checkout these awesome videos
http://paulirish.com/2010/10-things-i-learned-from-the-jquery-source/
http://paulirish.com/2011/11-more-things-i-learned-from-the-jquery-source/
on your first question, I dont think you seen window and document but something more like:
(function(doc) {
var fubar = doc.getElementById("fubar"); // === document.getElementById("fubar")
})(document);
you have a self-invoking function (or closure) with arguments like any function:
var b = function(str) { alert(str); }
b('hi there') //alert('hi there');
the same thing is it with the code above, but we are just calling the method at once we created it.
the other code you have:
( function($) {
//some code of widget goes here
})(Jquery);
is to reserve the $variable inside the metod to refer to the jQuery object, this is very handy if you have more frameworks or replaced the $ object with something else, everything inside that method with an $ will refer to the jQuery object and nothing else(if you don´t replace it inside your code).
the code:
$(function(){
$("#some_div").modal(); //here it's object the we got from the function
});
is calling jQuery and its a shortcut for $(document).ready
it will call the method:
function(){
$("#some_div").modal(); //here it's object the we got from the function
}
as soon as the DOM is ready
The pattern is called a closure. It makes sense to use when a module or function:
wants to avoid polluting globally-scoped variables
wants to avoid use globally-scoped variables and avoid other code polluting them
For an example of each, first take this pattern:
(function(window) {
// ...
})(window);
Everything inside the closure will be able to use window as if it were a local variable.
Next, take the same pattern using the JQuery symbol:
(function($) {
// ...
})($);
If you have some code that relies on a symbol/namespace like $, but another module reassigns that, it can screw up your code. Using this pattern avoids this by allowing you to inject the symbol into a closure.
Whenever you pass an argument to that wrapping function it's so that you won't mess up with any other libraries or global variables that may be present in your application.
For example as you may know jQuery uses $ as a symbol for calling itself, and you may also have another library, that will also use $ for calling itselt, under this condition you may have trouble referencing your libraries. so you would solve it like this:
(function($){
// here you're accessing jQuery's functions
$('#anything').css('color','red');
})(jQuery);
(function($){
// and in here you would be accessing the other library
$.('#anything').method();
})(otherLibrary);
This is specially useful when you're making jQuery or any other kind of library plugins.
What it does is allow you to use the $ variable inside your function in place of the jQuery variable, even if the $ variable is defined as something else outside your function.
As an example, if you're using both jQuery and Prototype, you can use jQuery.noConflict() to ensure that Prototype's $ is still accessible in the global namespace, but inside your own function you can use $ to refer to jQuery.

jQuery variable shadowing

There is strange pattern in jQuery:
var jQuery = (function() {
// Define a local copy of jQuery
var jQuery = function( selector, context ) {
...
return jQuery;
})();
What is the practical reason for this? Why not just expose the inner jQuery function? Is it only for name clashes in the inner jQuery and outer jQuery since both are in closures.
jQuery.noConflict(true) removes the global name for jQuery. However, it would be impossible to program the rest of the jQuery library without using some name for the object, so a local, non-exposed name needs to be used. For convenience, they redefine jQuery as a variable in the scope of the anonymous function.
The pattern itself is called module pattern. It´s not specific for jQuery and it´s not strange but very helpful. It allows for hiding of the objects state and implementation. It also allows for priveleged methods (public methods with access to private data) and other good design principles.

How to write functions in jQuery?

I'm going to be writing a callable function which will make use of jQuery. But I can't find any reference to ordinary function declaration with jQuery; it's all about element manipulation functions. Can I essentially just declare an ordinary javascript function and then use jQuery in it, or do I need to be doing something special? Is this okay?
function useJQ(xml)
{
var groups = {};
$('resultGroups', $(xml)).each(function() {
var count = $('results', this).length;
var name = $('name',this).text();
groups[name] = count;
}
You need not extend jQuery to do such tasks. You can use plain functions to do what you need to do. just ensure that you don't pollute the global namespace by setting your own namespace.
However, if just want to use the jQuery namespace instead of your own, here's a quick way to add them:
$.fn.functionName = function(){
//do what your function does
//"this" in here is the jQuery object you preceded the function
//to allow chaining, you must return a jQuery object
};
the effect is like:
$(selector).functionName()
jQuery is just a collection of helper functions. It doesn't affect how you define your functions. So your present code will work fine.
jQuery is not about structuring your javascript code, for that you should use Javascript enclosures, objects and prototype. There a many proposed ways of structuring Javascript code.
You could also take a look at defining jQuery plugins authoring to help you keep you code more organized.

How are functions scoped/namespaced within a <script> tag?

I'm working with a new application at work that we're building out using Knockout.js and jQuery. I prefer to "use strict" in my scripts, but since some of the libraries we're using don't work with "use strict" then I have to use the functional form.
I don't like placing javascript inside <script> tags inline, so I generally place everything in a separate file so it can be minified and gzipped by a pre-processor.
Given these criteria, I'm wondering how functions are scoped by default when you create them within a script tag. Right now I'm just doing something like this:
$((function(win) {
"use strict";
win.myFunction = function () {
// do stuff
};
}(window)));
As you can see I'm placing functions on my window object so I can call them in my view. I've noticed that I can call them in my jQuery templates without qualifying them (i.e.: I can just call myFunction instead if window.myFunction), but I'm concerned that this will not work across browsers. Do all browsers allow you to call functions placed in the window object without the fully-qualified name? How could I place a function in the global scope from within my anonymous method as I've defined above?
Thanks for the insight!
The window object essentially is the global scope. Any variable that isn't scoped to a function is a property of the window object.
You can set a global variable by setting it as a property of the window object, as you just about do:
window.myFunction = function() {
// do stuff
}
However, it's probably not a good idea to litter your global namespace with names. That way chaos, unmaintainable code and bizarre bugs come in. All jQuery functions, for example, are properties or sub-properties of the jQuery (or $) object. This means that they can define jQuery.each and not have to worry about collisions with a global each method. You should consider doing the same with your own code: create a single global namespacing object to house all your "global" methods.

Categories

Resources