Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/xpath/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 用js闭包替换js命名空间全局变量_Javascript_Namespaces_Closures_Globals - Fatal编程技术网

Javascript 用js闭包替换js命名空间全局变量

Javascript 用js闭包替换js命名空间全局变量,javascript,namespaces,closures,globals,Javascript,Namespaces,Closures,Globals,我在一个单页web应用程序中有一些共享代码,该应用程序当前正在使用“globals”命名空间将参数存储为全局变量 与污染全局“窗口”对象相比,使用名称空间是一种改进,但这段代码似乎是一个很好的闭包,可以在调用之间持久化值。我把一些想法弄得一团糟,但似乎无法正确理解闭包的语法 下面是当前版本的伪代码。所有代码都存在于“um”名称空间中。当我的共享函数最初被我应用程序中的一个新虚拟页面调用时,我需要存储一个名为“extraData”的JS对象的内容。函数的后续调用无法访问“extraData”,因此

我在一个单页web应用程序中有一些共享代码,该应用程序当前正在使用“globals”命名空间将参数存储为全局变量

与污染全局“窗口”对象相比,使用名称空间是一种改进,但这段代码似乎是一个很好的闭包,可以在调用之间持久化值。我把一些想法弄得一团糟,但似乎无法正确理解闭包的语法

下面是当前版本的伪代码。所有代码都存在于“um”名称空间中。当我的共享函数最初被我应用程序中的一个新虚拟页面调用时,我需要存储一个名为“extraData”的JS对象的内容。函数的后续调用无法访问“extraData”,因此如果underline.js确定参数是对象,我当前将其存储在um.globals.extraData“

//***************************
// IMPLEMENTATION SAMPLE
//***************************

// Define namespaces (not showing: um.grid, um.ajax, um.classes, um.constants, etc.)
window.um = window.um || {};

um.globals = um.globals || {}; /* container for namespaced 'global' variables */

um.grid.loadOrUpdate = function (iOffset, isUpdate, extra) {
    var ajaxParams = new um.classes.AjaxParams();
    //-----

    // If 'extra' is an object, store it in a global for subsequent invocations
    if (_.isObject(extra)) {
        // This seems like it could be a closure candidate...
        um.globals.extraData = extra;
    }

    ajaxParams.values = [um.constants.urlPathParams.grid];
    ajaxParams.verb = um.constants.httpVerbs.GET;

    // Use the global variable 'extraData'
    ajaxParams.extraData = um.globals.extraData;

    um.ajax.callMessaging(ajaxParams);
};
下面是一些用于实际调用函数的伪代码:

//***************************
// INVOCATION SAMPLES
//***************************

// 1st invocation from virtual page 'Alpha'
um.grid.loadOrUpdate(0, false, { "alpha-key": "alpha-value" });

// 2nd invocation from virtual page 'Alpha'
um.grid.loadOrUpdate(1, true); // will re-use the "alpha" object

// 1st invocation from virtual page "Beta'
um.grid.loadOrUpdate(0, false, { "beta-key": "beta-value" });

// 2nd invocation from virtual page 'Beta'
um.grid.loadOrUpdate(1, true); // will re-use the "beta" object
var alpha = um.grid.loadOrUpdate(0, { "key": "alpha-value" });
var beta = um.grid.loadOrUpdate(0, { "key": "beta-value" });
我如何杀死um.globals.extraData并用um.grid.loadOrUpdate内部的某种闭包来替换它

编辑

下面是一些来自“JavaScript模式”的代码,它们促使我提出这个问题:

var setup = function () {
    var count = 0;
    return function () {
        return (count += 1);
    }
};

// usage
var next = setup();
next(); // returns 1
next(); // returns 2
next(); // returns 3

这种方法是你想要的吗

var ns = {};
(function() {
 var globals;
 ns.func = function(update,opts) {
  if(update)opts=globals;
  else globals=opts;
  console.log(opts);
 }
})();

ns.func(false,"a");
ns.func(true);
ns.func(false,"b");
ns.func(true);
输出:

a
a
b
b

我在一个匿名函数中定义了globals变量的作用域,并使该函数中声明的函数在周围(在本例中为窗口)作用域中的对象上可用-因此它可以访问“globals”变量,但在其外部不可见。

对我来说,不清楚您试图通过闭包实现什么。闭包允许您在当前范围内封装变量的状态,如果您试图创建对象的各种实例,每个实例都有自己的
额外的
状态,这可能很方便

您可以通过实现
loadOrUpdate
来实现这一点,这种方式可以返回对函数的引用,以后可以调用该函数。调用该函数时,该范围内的所有变量都将被封闭,并保留函数创建时的值

例如:

um.grid.loadOrUpdate = function (iOffset, extra) {
    var ajaxParams = new um.classes.AjaxParams();
    //-----

    ajaxParams.values = [um.constants.urlPathParams.grid];
    ajaxParams.verb = um.constants.httpVerbs.GET;

    um.ajax.callMessaging(ajaxParams);

    // Return a function used to update this data later
    return function (newOffset) // Update function
    {
       // From within here, you'll have access to iOffset and extra as they exist at this point
       window.alert("Key: " + extra.key + " - Changing offset from " + iOffset + " to " + newOffset);
       iOffset = newOffset;
    };
};
然后可以像这样调用函数,记住它将返回对函数的引用:

//***************************
// INVOCATION SAMPLES
//***************************

// 1st invocation from virtual page 'Alpha'
um.grid.loadOrUpdate(0, false, { "alpha-key": "alpha-value" });

// 2nd invocation from virtual page 'Alpha'
um.grid.loadOrUpdate(1, true); // will re-use the "alpha" object

// 1st invocation from virtual page "Beta'
um.grid.loadOrUpdate(0, false, { "beta-key": "beta-value" });

// 2nd invocation from virtual page 'Beta'
um.grid.loadOrUpdate(1, true); // will re-use the "beta" object
var alpha = um.grid.loadOrUpdate(0, { "key": "alpha-value" });
var beta = um.grid.loadOrUpdate(0, { "key": "beta-value" });
调用
alpha()
beta()
时,extra的值将通过闭包保留,因此不需要保留对它的全局引用

alpha(1); // Update from 0 to 1
alpha(2); // Update from 1 to 2
beta(3); // Update from 0 to 3
beta(4); // Update from 3 to 4


但是,如果您试图保留所有对
loadOrUpdate
的调用共享的
extra
的单个实例,则最好使用以前的技术,将当前值存储为函数本身的属性,或者该函数范围内的任何其他地方。

您的实现似乎仍然非常接近我的实现,其中使用“ns.func”之外的全局变量来捕获“opts”。我将使用“Javascript模式”中的闭包示例更新我的原始问题,该示例最初让我认为内联闭包是消除全局变量的方法。这不是一样吗?将变量隐藏在函数范围内?在我的示例中,变量“globals”在全局范围内不可见。这个名称不好,但我保留了它,以表明它在您的原始示例中的用途。变量“globals”隐藏在匿名函数的作用域中。这里有一个参考,以防术语混淆(我只是自己查了一下!):“引用外部函数的局部变量的内部函数创建闭包”。。。这就是我在示例中得到的,一个由内部函数引用的变量,在外部函数中作用域,在全局作用域中不可见。与Crockford的私有变量实现IIRC类似,我认为JavaScript中的“适当”闭包需要返回函数。我的原始实现和您的版本都不返回函数,它们只是将值存储在一个从全局“窗口”范围隐藏的变量中。我在考虑返回另一个函数的某种内部函数,如我在问题底部添加的“setup/next”示例。我认为区别在于,在我的示例中,变量
globals
是真正隐藏的,即除了内部函数之外,任何东西都无法访问,而在您的第一个示例中,变量可以通过
um.globals
在全局范围内访问,这符合我上面链接的闭包的定义。但我同意你最后一次对迈克的回答的评论——你所拥有的可能很好;)我开始认为,去掉我的名字空间“global”可能不适合在“loadOrUpdate”中关闭。正如您所指出的,我只需要一个“loadOrUpdate”实例,而最初的实现非常有效。“um.globals…”中的值不会污染窗口名称空间,而“globals”的名称清楚地表明,其中存储的任何值的作用域都是“um…”中的全局范围。我认为这是一种试图过度优化或过度设计已经正常工作的东西的情况。全局变量本质上不是邪恶的。:-)