0

我想知道是否可以在不同的模块中共享变量。

例如,在我的common模块中,我定义了一些全局变量和 util 方法

(function(){
  var name="";
})();

在另一个模块中,我想访问name变量,例如,在app模块中:

var kk=name; // access the name
//other thing

但是我不想将其导出name到全局上下文。

是否可以?

更新


为什么我问这个问题是我发现谷歌这样做:

在谷歌地图示例页面中:

它加载以下js: main.js

谁的内容是:

((function(){ //xxxxxx }).call(this);

然后它像这样加载地图组合:

谷歌地图。_ gjsload _ ('map', '\'use strict\';function Ut(){}function Vt(a,b,c).......');

map模块可以使用模块中的变量main

4

2 回答 2

1

编辑:

非常简单:如果您在示例页面上打开控制台,并查看 main.js 的源代码(单击左下角类似 的按钮[{}]),您会注意到整个脚本是一个大函数,即被称为使用.call(this)。后者是必要的,因为严格模式(它屏蔽了全局对象,除非它被显式设置为调用者上下文)。
这个函数声明了这个函数范围内的所有函数、对象和方法,形成一个闭包。因此,在这个范围内声明的所有函数也可以访问所有变量。最后,该google属性被分配为全局对象的属性,从而暴露了闭包。

(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

据我所知,这可能看起来并不那么清楚,但从本质上讲,发生了什么:每个函数都有自己的范围。当该函数返回时,在该范围内声明的所有变量都会被垃圾收集(GC'ed),除非有一个对象引用它们。
在这种情况下,google 是一个对象,在匿名函数的范围内声明。然后将此 google 对象的引用分配给全局对象,它恰好与对象变量具有相同的名称,但它也可以像这样公开:

window.foobar = google;
window.foobar.closureScope;//works
window.google;//undefined

Google 是全局对象的一个​​属性,它引用在函数范围内创建的对象。它引用的对象使函数的作用域(以及在该作用域中声明的所有变量)保持活动状态。这就是为什么看起来您几乎可以直接访问闭包变量的原因,但同样,它是一个REFERENCE。如果您熟悉 C(++) 编程,以下是伪代码中发生的情况:

GoogleObj google = new Google();
GoogleObj &window.google = google;
//or in pseudo-C:
GoogleObj *google;
GoogleObj **window.google = &google;//pointer to pointer ~= reference

基本上,全局google只包含实际 google 对象的内存地址,它指向它,它引用它,它只是告诉 JS 在哪里查找内存中的值,......
实际对象不能直接访问,它与所有与它一起声明的局部变量一起位于内存中的某个位置,它们也都有地址,但全局对象不知道这些。它只是去它知道的一个地址,询问它需要的任何东西,并且原始的google 对象符合。

我很难以连贯、全面的方式解释所有这些,但也许这篇文章可能会对这个问题有所了解。当我开始研究闭包时,我发现这些图表很有帮助。


你不能,不是这样。闭包的全部意义在于您可以设置只能在该特定范围内引用的变量。但是,您可以做的是使用特权方法,或者(不是很好的做法,但可能)完全将变量分配给全局对象。

(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

如果你真的,真的需要全局变量:

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'

但最重要的是,特别是在您的情况下(访问某些“私有”变量),特权 getter 似乎是最好的方法:

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

应该这样做

于 2012-09-14T11:38:52.673 回答
0

在正确批评昆汀和埃利亚斯后更新

你可以像这样定义你的模块:

var module = (function(){
    // your module definition
    var module = {};

    // set name as a property of the module
    module.name="";

    // return the module object
    return module;
})();

现在使用在模块外部访问名称

var kk = module.name;
于 2012-09-14T11:30:09.463 回答