Reputation: 36028
I want to know if it is possible to share variables in different module.
For example,in my common
module,I define some global variable and util methods
(function(){
var name="";
})();
While in anothe module,I want to access the name
variable,for example, in the app
module:
var kk=name; // access the name
//other thing
However I do not want to export the name
to global context.
Is it possible?
Why I ask this question is I found google do this:
In the google map example page:
It load the following js: main.js
Whose content is:
((function(){ //xxxxxx }).call(this);
Then it load the map compnets like this:
google.maps._gjsload_('map', '\'use strict\';function Ut(){}function Vt(a,b,c).......');
While the map
module can use the variables in the main
module.
Upvotes: 0
Views: 972
Reputation: 76395
Edit:
It's perfectly simple: if you open your console on the example page, and look at the source of main.js (click the button in the bottom left corner that looks like [{}]
) you'll notice that the entire script is one big function, that is called using .call(this)
. The latter is necessary because of strict mode (which shields the global object, unless it's explicitly set as caller context).
This function declares all functions, objects and methods in this function's scope, forming a closure. It therefore stands to reason that all functions declared in this scope have access to all variables, too. In the end the google
property is assigned as a property of the global object, thus exposing the closure.
(function()
{
'use strict';
console.log(this);//would be undefined
}).call(this);//but the global object is explicitly set as context, so this === window
(function()
{
'use strict';
var closureScope = 'Global object can\'t see me';
var google = {visible:'Yes, I was assigned as a property to the global object'};
google.closureScope = closureScope;//expose initial value of closureScopeVariable
google.showBenefits = function()
{//context here is google object, this points to google
this.closureScope = 'I looked like the closure variable';//reassign
console.log(this.closureScope === closureScope);//logs false
};
google.restoreOriginal = function()
{
this.closureScope = closureScope;//reassign closureScope's original value
};
//expose:
this.google = google;
}).call(this);
//global object:
google.closureScope = 'Foobar';
google.restoreOriginal();
console.log(google.closureScope);//Global object can't see me
For all I know this might not look all that clear, but essentially, what happens is this: each function has its own scope. All variables declared in that scope are garbage collected (GC'ed) when that function returns Unless there is an object that references them.
In this case google is an object, declared in the anonymous function's scope. A reference to this google object was then assigned to the global object, it just happens to have the same name as the object variable, but it could just as well have been exposed like so:
window.foobar = google;
window.foobar.closureScope;//works
window.google;//undefined
Google is a property of the global object, that references an object created in the function's scope. The object it references keeps the function's scope (and all of the variables declared in that scope) alive. That's why it might seem that you have access to the closure variables almost directly, but again, it's a REFERENCE. If you're familiar with C(++) programming, here's what happens in pseudo-code:
GoogleObj google = new Google();
GoogleObj &window.google = google;
//or in pseudo-C:
GoogleObj *google;
GoogleObj **window.google = &google;//pointer to pointer ~= reference
Basically the global google
contains nothing more then the memory address of the actual google object, it points to it, it references it, it just tells JS where to look for the values in memory,...
The actual object cannot be accessed directly, it sits somewhere in memory, along with all local variables that were declared along with it, who all have addresses, too, but the global object doesn't know about those. It just goes to the one address it knows of, asks for whatever it needs and the original google object complies.
I'm terrible at explaining all this in a coherent, comprehensive way, but perhaps this article might shed some light on this matter. When I started to look into closures, I found the diagrams very helpful.
You can't, not as such. The whole point of closures is that you can set variables that can only be referenced in that specific scope. What you can do, however is use priviliged methods, or (not to good practice, but possible) full on assigning a variable to the global object.
(function()
{
var name = 'foo';
//do stuff
window.name = name;//expose to global object
})();//THIS IS BLUNT AND DANGEROUS
var safer = (function()
{
var name = 'foo';
return {name:name};
});
console.log(safer.name);//logs foo
If you really, really need globals:
var safer = (function()
{
var closureVars = {name:'foo'};
var name = 'foo';
return function(privateName,globalName)
{
globalName = globalName || privateName;
window[globalName] = closureVars[privateName];
};
});
safer('name');//sets window.name to 'foo'
But best of all, especially in your case (access certain "private" variables) a privileged getter would seem the best way to go:
var module = (function()
{
var closureVars = {name:'foo';}
return {get:function(name)
{
return closureVars[name];
},
set:function(name,val)
{
closureVars[name] = val;
}
};
};
var name = module.get('name');//sets a global name variable to 'foo'
module.set('name2',module.get('name'));//and so on
That should do it
Upvotes: 1
Reputation: 9975
UPDATED after correct criticism of Quentin and Elias
You could define your module like this:
var module = (function(){
// your module definition
var module = {};
// set name as a property of the module
module.name="";
// return the module object
return module;
})();
And now access name outside of the module using
var kk = module.name;
Upvotes: 0