I'm working with several functions which need to pass a variable back and forth. Should I use a global variable or another method instead? I would also appreciate an example or two on how to implement it.
Thanks, Elliot Bonneville
Psuedocode of my functions:
function GetXML() {//this would be a function which reads in an XML file.
//Preferably it would also generate or set an object to hold the XML data.
}
function UseXMLData() { //I would use the XML data here.
}
function UseXMLDataHereAsWell() { //And here as well.
}
Global variables are, as you probably guessed, considered bad. Any other code on the page can modify them - often because another programmer accidentally picks the same name. You can try to mitigate this effect by choosing really strange names, but then you get a bunch of really strange names.
There are a lot of ways to minimize the number of global variables you create in JavaScript. One way is to store all your variables under a single object - that's what jQuery does (Technically jQuery uses two - $ and jQuery.)
If you know what you're doing, you often don't have to create any global variables - just wrap all your code in a function that you invoke immediately.
Bad example - pollutes the global namespace unnecessarily:
var appleCount = 0;
function addApple() {
appleCount = appleCount + 1;
}
function howManyApples() {
return appleCount;
}
addApple();
alert(howManyApples());
Better example - only creates one global variable:
var appleCounter = {
count: 0,
add: function() {
this.count = this.count + 1;
},
howMany: function() {
return this.count;
}
};
appleCounter.add();
alert(appleCounter.howMany());
Best example - creates no global variables:
(function(){
var appleCounter = {
count: 0,
add: function() {
this.count = this.count + 1;
},
howMany: function() {
return this.count;
}
};
appleCounter.add();
alert(appleCounter.howMany());
})();
The best solution for what you're trying to do would be to wrap all your data into an object and make your functions be methods on the object:
function MyXMLClass() {
this.data = null;
}
MyXMLClass.prototype = {
GetXML: function() {
this.data = ...;
},
UseXMLData: function() {
// use this.data
},
/* etc. */
};
And then you can just use it like this:
var x = new MyXMLClass();
x.GetXML();
x.UseXMLData();
...
Global variables should be avoided in reusable scripts.
If you're writing simple functions that will only be used in one page, there's nothing wrong with using globals.
If you're writing a reusable component or a complex web page, you should use closures or namespaces instead.
For more specific advice, please provide more detail.
EDIT:
You should create an XmlData class.
For example:
function XmlData(...) {
this.data = ...;
}
XmlData.prototype.doSomething = function(...) {
//Use this.data
}
Depending on how what your data comes from, you may want to make a separate function to retrieve the data.
Here is a good explanation.
Create a namespace, put all your functions within that namespace.
MyNS = {
x: 1, y: 2 // Here you define shared variables
};
MyNS.func1 = function(){}; // Here you define your functions that need those variables
Avoid global variables, it's bad programming. Try pass it as an argument or use name spacing to restrict its scope.
Related
I am trying to understand Javascript module patter, but I can't figure out the difference between parameters added to the anonymous function and parameters added at the end. So can someone please help me understand the difference between both? Thanks
Below is a module pattern example which implement both anon. function parameters (JQ, Yahoo) and module parameters shown at the end (JQuery, Yahoo).
var modularpattern = (function(JQ, Yahoo) {
var sum = 0 ;
return {
add:function() {
sum = sum + 1;
return sum;
},
reset:function() {
return sum = 0;
}
}
}(JQuery, Yahoo));
Logically your codes is equal to:
var func = function(JQ, Yahoo) { // Section 1
var sum = 0 ;
return {
add:function() {
sum = sum + 1;
return sum;
},
reset:function() {
return sum = 0;
}
}
}
var modularpattern = func(JQuery, Yahoo); // Section 2
So in section 1
JQ : A function local variable which is used as input argument
Yahoo : Exactly same as JQ
And in section 2 (In this section actually you invoke the function )
JQuery : An existing object in the global scope
Yahoo : Exactly same as JQuery
Why do developers implement like this:
All global objects is accessible inside function scopes but accessing to local variables is much faster than global variables. (This is called Localization)
I can't figure out the difference between parameters added to the anonymous function and parameters added at the end
The parameters added to the anonymous function are the names you're giving to these things inside your function
The parameters added at the end are the references to these objects
This means you can access a "safe(r)" reference, as it's less easily changed by other pieces of code
(function (bar) {
// use bar here, not foo as it's your protected reference
// but unless something else happens, bar === foo
}(foo);
Code using this pattern is good for several reasons
Keeps the namespace clean
If frameworks contain conflicts, gives you an "safe" environment to work in where you can use the default names
I had work with many realizations of Module Pattern, but this one is the best way:
(function(global) {
var somePrivate = 'foo';
function somePrivateMethod() {}
var myModule = function() {
// Your logic here
}
global.myModule = myModule;
})(this);
I understand the concept of variable scope in the following example, but can someone explain the function-wrapping syntax (...)();, e.g. how do you use it in actually day-to-day JavaScript programming? It's not something that I know from PHP/Java/C#.
window.onload = function() {
var i = 4;
console.log(i); //4
(function showIt() {
var i = 'whatever';
console.log(i); //whatever
})();
console.log(i); //4
};
There are several ways in which this form is useful. One is to lexically scope a segment of code so that its inner variables and methods stay separate from the larger body of code that contains it. In this way, it's JavaScript's way of doing block scoping. But the most common way I use this format is as an alternative to this:
var ret = {
depth:0,
initialized:false,
helper:function() { /*help with some stuff*/ },
initialize:function(){ /*do some initialization code*/ },
action:function(){/*do the thing you want*/}
destroy:function() { /*clean up*/ }
}
The thing that absolutely kills me about this format is it is extremely time consuming to find missing braces and commas. For example, the code above won't work because the's no comma at the end of the action declaration and unless I had pointed it out, you'd have had a hard time finding the problem because when the exception is thrown, it's thrown on the entire statement, not the section that's "causing the problem". This is such a predictable problem that I simply don't use this format any more if I can possibly avoid it. I refuse. Instead, the same can be written much more clearly as:
var ret = (function(){
var self = {},
initialized = false;
var helper = function() { /*help with some stuff*/ };
self.depth = 0;
self.initialize = function() {/*do some initialization*/};
self.action = function() {/*do the thing you want*/};
self.destroy = function() { /*clean up*/ };
return self;
}());
There are two big advantages for me. One, missing braces and commas can be found more easily (when the exception is thrown, the line number will be close to the area where it's missing). And two, you can choose to keep some variables and methods private and you retain all the benefits of the first block of code.
And the last plug I'll give for this format is that the code above (which is sort of like a Singleton) can be converted into a constructor by 1) removing the invocation braces on the outside, 2) changing self = {} to self = this, and 3) optionally removing the return self at the end:
var Ret = function(){
var self = this,
initialized = false;
var helper = function() { /*help with some stuff*/ };
self.depth = 0;
self.initialize = function() {/*do some initialization*/};
self.action = function() {/*do the thing you want*/};
self.destroy = function() { /*clean up*/ };
return self; // this is ignored by the compiler if used as a constructor
};
var ret = new Ret();
This is defining a function showIT (using function showIT() {...}) similar to what you're already familiar with. The () at the end directly invokes the function in the same line as it is defined. That's probably the part that is new to you. Just like you'd say showIT() to invoke the function, you can replace the name with the actual definition and it'll work in Javascript.
JavaScript has function literals. All it's doing is making a function literal, and calling the result of the expression. Is the name what's confusing you? All a name would be used for is referring to the function inside its own body, and it's optional. (Note that that's not compatible with IE 8 and earlier.)
Unlike in C where variable names have block scope, JavaScript (like Pico) has only function scope.
So if you want to create a new name scope you can't just use { ... } as you could in C, you have to use (function() { ... })();.
It is possible to access ther oute scope of a function?
I will explain better.
I've a function, from which I want to acccess its calling function scope.
function called() {
// i want to access the calling outer function scope
}
function calling() {
called();
}
obviusly called() function could be called by a lot of calling functions, and called() has to know time to time which function has called him,` and access its scope variables and functions.
No, that isn't possible.
To access a variable from two functions you need to either:
Declare it in a shared scope
var the_variable;
function called() {
// i want to access the calling outer function scope
}
function calling() {
called();
}
Pass it as an argument
function called(passed_variable) {
return passed_variable;
}
function calling() {
var some_variable;
some_variable = called(some_variable);
}
You should pass any relevant information into called() as parameters:
function called(x, y, z) {
}
function calling() {
var x = getX();
var y = computeY();
var z = retrieveZ();
called(x, y, z);
}
If you expect called to do different things, and receive different contextual information, depending on who calls it, you should probably make it multiple separate functions.
function called(outterScope) {
// outterScope is what you want
x = outterScope.declaredVariable;
outterScope.declaredFunction();
}
function calling() {
this.declaredVariable = 0;
this.declaredFunction = function() { // do something };
var _self = this;
called(_self);
}
No,
if you need to use variables from scope of calling code block (example function)
you have to pass them in arguments
or you can create object and access properties in Object scope (via this.param_name)
Depending on what you want to do, there might be better ways to do it, but if absoultely have to resort to it, you may find that out via Function.caller:
function myFunc() {
if (myFunc.caller == null) {
return ("The function was called from the top!");
} else
return ("This function's caller was " + myFunc.caller);
}
Do note that its not part of the standards, even though some major browsers and IE7 support it.
Also, you cannot access the caller functions scope or variables. Its usability is limited to finding out who called you (helpful for logging or tracing).
I'm trying to reuse a complicated function, and it would work perfectly if I could change the value of a local variable that's inside a conditional inside that function.
To boil it down:
var func = complicated_function() {
// lots of code
if (something) {
var localvar = 35;
}
// lots of code
}
I need localvar to be some other number.
Is there any way to assign localvar to something else, without actually modify anything in the function itself?
Update: The answer is yes! See my response below.
Is there any way to assign localvar to something else, without actually modify anything in the function itself?
Nope.
No, but it is possible to assign it conditionally so that the function signature (basically, the required input and output) does not change. Add a parameter and have it default to its current value:
var func = complicated_function(myLocalVar) {
// lots of code
if (something) {
// if myLocalVar has not been set, use 35.
// if it has been set, use that value
var localvar = (myLocalVar === undefined)?35:myLocalVar;
}
// lots of code
}
No.
Without changing the complicated function there is no way, in javascript you can manipilate this by using call and apply. You can override functions in the complicated function or add new if this is an option (but they won't be able to access the local variable localvar).
this is more for fun my real answer is still no.
If you are feeling crazy :)
var complicatedFunction = function() {
var i = 10;
var internalStuff = function() {
console.log(i); // 10 or 12?
};
return internalStuff();
};
var complicatedFunction;
eval("complicatedFunction = " + complicatedFunction.toString().replace(/i = 10/, 'i = 12'));
complicatedFunction(); //# => 12
If the function uses this.localvar:
var func = function() {
alert(this.localvar)
if (true) {
var localvar = 35;
}
// lots of code
alert(this.localvar)
}
var obj = {localvar: 10};
func.call(obj); // alerts 10 twice
If not, then you can't change it without changing the function.
In javascript variables are "pushed" to the top of their function. Variables in javascript have function scope, not "curly brace" scope like C, C++, Java, and C#.
This is the same code with you (the developer) manually pushing it to the top:
var func = complicated_function() {
var localvar = 0;
// lots of code
if (something) {
localvar = 35;
}
// lots of code
}
Does declaring the variable "up" one function help you out? At least the declaration is isolated.
function whatever() {
var localvar = 0;
var func = function() {
var something = true;
// lots of code
if (something) {
localvar = 35;
}
// lots of code
};
func();
alert(localvar);
}
whatever();
Here is the jsFiddle: http://jsfiddle.net/Gjjqx/
See Crockford:
http://javascript.crockford.com/code.html
JavaScript does not have block scope, so defining variables in blocks can confuse programmers who are experienced with other C family languages. Define all variables at the top of the function.
I asked this question about three weeks ago and within a half hour got five answers that all basically told me it wasn't possible.
But I'm pleased to announce that the answer is YES, it can be done!
Here's how:
var newfunc = func.toString().replace('35', '42');
eval('newfunc = ' + newfunc);
newfunc();
Of course, it uses eval, which probably means that it's evil, or at least very inadvisable, but in this particular case, it works.
I have a rather large set of javascript functions that I am working on refactoring into a set of classes using Prototype.
I was wondering if there was a way I could make binding anonymous functions to the class simpler? I keep forgetting to add the bind this at the end. Or is this just the way it is done all the time?
var arr = this.getSomeArray();
arr.each(function(t) {
t.update(val);
this.updateJSValue(t);
}.bind(this));
Your options are basically to call some function (bind, addMethods or another function you write) or use a local variable rather than this:
var self=this;
arr.each(function(t) {
t.update(val);
self.updateJSValue(t);
});
If you've a large number of functions, the local variable requires the least typing For just a few functions, there isn't too much difference.
function ThingMixin(self) {
self.foo = function(arr) {
arr.each(function(t) {
t.update(val);
self.updateJSValue(t);
});
};
...
};
...
ThingMixin(Ralph.prototype);
// or an anonymous function:
(function (self){
self.foo = function(arr) {
arr.each(function(t) {
t.update(val);
self.updateJSValue(t);
});
};
...
})(Ralph.prototype);