0

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?

Update


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.

2 Answers 2

1

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

Sign up to request clarification or add additional context in comments.

9 Comments

@hguser: I've updated my answer, well, now I'm afraid it's just unintelligible dribble, but there's a link on how closures work somewhere in there, which might prove useful. Also check John Resig's blog on strict mode, and read some of Crockfords articles or watch his vids on youtube. It might take a while, but all of a sudden it'll all make sense, promise ;)
Thanks for your long answer. However I have two question:1 in the main.js, the first line,there is a funcion aa,and I do not find it is exported by google.aa=aa 2 in the map.js,it can access aa directly, just like aa is defined in the map.js directly. What is the problem?
There's more than 1 closure going on, so it can be confusing. I haven't got the time (and courage) to read through the entire, slightly obfuscated code either. What I can say, though, is that not all functions in the closure have to be assigned to the exposing object. That function throws an error, so It's best not to expose it, otherwise you might write google.aa() by mistake, stopping your script. It could well be that an ajax method of the google object throws an error at some point, and for that the function aa can be called, but the method has that scope access,
That's what closures are for: preserve relevant code in such a way that other code, either an other lib, or code written by the user doesn't interfere with the inner workings. I can't seem to find that map.js you're on about, but provide a link and I'll look into it. I've been meaning to write an article on this subject for a long time anyhow. PS: don't want to nag, but if my answer was helpful, I do appreciate an up-vote... I think it's fair to say I have made an effort here
Thanks!. The map.js link can be found at my post. And here is a example: in the main.js there is a variable m(m=window,da=Infinity,ea=document) which refer to the window,and in the map.js you can find that the m is used directly(m[Lj](this.f)) while the Lj is defined at main.js also.
|
0

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;

1 Comment

No, in that context you are creating window.name, not module.name

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.