What is best practice to get a variable outside of its anonymous function without polluting the global namespace?
A number of possibilities:
Create a properly name-scoped public accessor function to obtain the value upon demand.
Pass the value to the functions where it will be needed
Pass a private accessor function to the other module
Put the variable in a properly name-scoped global
Pass a "data object" to the other module that has the value in it (along with other values)
Which makes the most sense depends upon how much data you need to share, how widely it needs to be shared, whether the sharing is both ways, etc...
The typical design pattern for exposing global data with the minimum impact on polluting the global namespace is to do something like this:
var JF = JF || {}; // create single global object (if it doesn't already exist)
JF.getMyData = function() {return(xxx);}; // define accessor function
JF.myPublicData = ...;
Then, anywhere in your app, you can call JF.getMyData(); or access JF.myPublicData.
The idea here is that all public methods (or even data objects) can be hung off the JF object so there's only one new item in the global space. Everything else is inside that one object.
There have been several CoffeeScript questions along these lines:
How do I define global variables in CoffeeScript?
Expose a javascript api with coffeescript
Getting rid of CoffeeScript's closure wrapper
as well as several others that are environment-specific. If you posted a more detailed question with a concrete example, I could provide a more specific answer.
Related
Today while working my mind was stack at some point in javascript.
I want to know that what is basic difference between
function FunctionName(){
//Code goes here;
}
And
var MyFuncCollection = new Object();
MyFuncCollection.FunctionName = function(){
//Code goes here;
}
Both are working same. Then what is difference between then. Is there any advantage to use function with object name?
I have read Question. But it uses variable and assign function specific variable. I want to create object and assign multiple function in single object.
The first one defines a global function name. If you load two libraries, and they both try to define FunctionName, they'll conflict with each other. You'll only get the one that was defined last.
The second one just has a single global variable, MyFuncCollection. All the functions are defined as properties within that variable. So if you have two collections that try to define the same function name, one will be FuncCollection1.FunctionName, the other will be FuncCollection2.FunctionName, and there won't be any conflict.
The only conflict would be if two collections both tried to use the same name for the collection itself, which is less likely. But this isn't totally unheard of: there are a few libraries that try to use $ as their main identifier. jQuery is the most prominent, and it provides jQuery.noConflict() to remove its $ binding and revert to the previous binding.
The short answer is, the method in object context uses the Parent Objects Context, while the "global" function has its own object context.
The long answer involves the general object-oriented approach of JavaScript, though everything in JavaScript is an object you may also create arrays with this Method.
I can't really tell you why, but in my experience the best function definition is neither of the top mentioned, but:
var myFunction = function(){};
It is possible to assign function to variables, and you may even write a definition like this:
MyObject.myMethod = function(){};
For further reading there are various online Textbooks which can give you more and deeper Information about this topic.
One main advantage I always find is cleaner code with less chance of overwriting functions. However it is much more than that.
Your scope changes completely inside the object. Consider the following code ::
Function:
function FunctionName(){
return this;
}
FunctionName()
Returns:
Window {top: Window, location: Location, document: document, window: Window, external: Object…}
Object:
var MyFuncCollection = new Object();
MyFuncCollection.FunctionName = function(){
return this;
}
MyFuncCollection.FunctionName()
Returns:
Object {}
This leads to some nice ability to daisy chain functions, amongst other things.
The first:
function functionName (){
//Code goes here;
}
Is a function declaration. It defines a function object in the context it's written in.
Notice: this doesn't have to be the global context and it doesn't say anything about the value of this inside it when it's invoked. More about scopes in JavaScript.
Second note: in most style guides functions are declared with a capitalized name only if it's a constructor.
The second:
var myFuncCollection = {};
myFuncCollection.functionName = function () {
//Code goes here;
};
notice: don't use the new Object() syntax, it's considered bad practice to use new with anything other then function constructors. Use the literal form instead (as above).
Is a simple assignment of a function expression to a property of an Object.
Again the same notice should be stated: this says nothing about the value of this when it's invoked.
this in JavaScript is given a value when the function object is invoked, see here for details.
Of course, placing a function on an Object help avoiding naming collisions with other variables/function declarations in the same context, but this could be a local context of a function, and not necessarily the global context.
Other then these differences, from the language point of view, there's no difference whatsoever about using a bunch of function declarations or an Object with bunch of methods on it.
From a design point of view, putting methods on an Object allows you to group and/or encapsulate logic to a specific object that should contain it. This is the part of the meaning of the Object Oriented Programming paradigm.
It's also good to do that when you wish to export or simply pass all these functions to another separate module.
And that's about it (:
I often use the pattern of a main JavaScript constructor function and adding methods to its prototype object so they can be called intuitively by the user, for example:
function Slideshow(options) {
this.options = options
this.slideshow = $('#slideshow')
//more variables here
}
Slideshow.method1 = function () {
this.slideshow.addClass('test') // do something with slideshow variable
};
Slideshow.method2 = function () {
// another method
};
The one thing that really bugs me about this pattern is how in order to make variables accessible across all prototype methods, I have to add "this" in front of each variable inside the constructor function. It's a major pain, and I can't help but think there's a more elegant way to do this.
If I forgo using the prototype object and just add the methods as instance methods, I know I can't get around this problem, but I like the efficiency? and self encapsulating nature of this pattern. Any other suggestions for a better pattern? Thanks!
It's a major pain
No, it's really not. Every single JavaScript developer uses this syntax. If you were in Ruby or Python, you'd use self., in PHP you'd use $this->. Some languages like C++ don't require any special decorator, but JavaScript does.
and I can't help but think there's a more elegant way to do this.
No, there isn't.
This is JavaScript's syntax, you cannot change it, and you cannot work around it. If you want to access a property of this, you need this. before the property name. Otherwise, you're talking about global variables.
If you want a different syntax, consider a different language like CoffeeScript, which compiles to JavaScript.
meager has pretty much summed things up if you're talking about accessing public instance properties or methods. You have to use this in front of it as that's just how the language works.
But, if you have private instance properties or methods, you can define those as local variables inside the constructor and you can access them without this.
function slideshow(options) {
// no need to resave the options arguments as they can be used
// directly from the argument variable
// define a per-instance private variable that other methods defined
// within the constructor can use directly without the use of `this`
var theShow = $(options.selector || '#slideshow');
// define public methods
this.method1 = function() {
// can access private instance variable here without this in front of it
theShow.addClass('test');
}
this.method2 = function() {
theShow.addClass(options.decoaration);
}
}
This general design pattern is described here: http://javascript.crockford.com/private.html
Practically speaking, this works because the constructor function with the public methods declared inside it creates a closure that lasts for the duration of the object lifetime so the local variables in the constructor become per-instance variables accessible only from the functions declared within the constructor.
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'm new to JavaScript, and have a simple (I presume) question regarding best practices for accessing variables in functions:
When should I declare a global variable, as opposed to simple passing a value into a function?
Declaring a global variable should only be used as an option of last resort.
Global variables are bad in general and especially so in javascript. There is simply no way to prevent another piece of javascript from clobbering your global. The clobbering will happen silently and lead to runtime errors.
Take the following as an example.
// Your code
myParam = { prop: 42 };
function operateOnMyParam() {
console.log(myParam.prop);
}
Here i've declared 2 global variables
myParam
operateOnMyParam
This might work fine while testing your javascript in isolation. However what happens if after testing a user combines your javascript library with my javascript library that happens to have the following definitions
// My code
function myParam() {
console.log("...");
}
This also defines a global value named myParam which clashes with your myParam. Which one wins depends on the order in which the scripts were imported. But either way one of us is in trouble because one of our global objects is dead.
There are many, many reasons.. but an easy one is.. The argument of a function only exists in the function, while it's running. A global variable exists all the time, which means:
it takes up memory until you manually 'destroy' it
Every global variable name needs to be unique
If, within your function.. you call another function.. which ends up calling the first function, all of a sudden you may get unexpected results.
In short: because the function argument only lives for a really short time and does not exist outside the function, it's much easier to understand what's going on, and reduced the risk of bugs greatly.
When dealing with framework-less JavaScript I'll store my simple variables and functions in an object literal as to not clutter up the global namespace.
var myObject = {
variableA : "Foo",
variableB : "Bar",
functionA : function(){
//do something
//access local variables
this.variableA
}
}
//call functions and variables
myObject.variableA;
myObject.functionA();
I'm writing a quite complex JavaScript application that has an MVC architecture that I'm implementing using Prototype's Class support and the Module pattern. The application uses AJAX and the Observer pattern. I create my controller instance when the DOM has loaded, pass it a view and some models created from JSON data and away it goes.
However, I've found that I have to set my controller instance as a property on the Window object—i.e. declare it without using var—because I have an AJAX success callback that refreshes the view object owned by the controller and at this point in the code my nice little MVC world is not in scope.
I investigated passing in the view object as a parameter to the function containing the AJAX code, but this got really messy and would have led to some horrible violations of the MVC pattern, such as coupling the model and the view. It was horrendous.
Is doing things like storing my controller instance directly on Window considered bad form? It smells a bit like using a global variable to me, but I can't see any way around it.
Setting properties on the window object is equivalent to creating global variables. That is, sometimes doing it is inevitable, but you should try to keep it to a bare minimum, as it ends up polluting the global namespace.
In your case, creating a single property is not so bad. If you want to be extra careful about it, you can explicitly create a namespace for any stuff you need global access to:
// In init:
var mynamespace = {};
. . .
// Once the controller is available:
var namespace = window.mynamespace;
namespace.controller = controller;
namespace.foo = bar; // Set other stuff here as well.
I would say it's bad practice. You can always, and easily, create a namespace for your application and put globals in there, if you must.
They are useful when you want to call a global function whose name is not known beforehand.
var funcName = "updateAns" + ansNum;
window[funcName]();
They can be used to
a) avoid evil evals in most cases.
b) avoid reference errors to global variables.
x = x + 1 will generate a reference error if a global x is not defined.
window.x = window.x + 1 will not