3

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

使用命名空间是对污染全局“窗口”对象的改进,但似乎这段代码是闭包在调用之间保持值的一个很好的候选者。我搞砸了一些想法,但似乎无法正确理解闭包的语法。

这是当前版本的伪代码。所有代码都位于“um”命名空间中。当我的共享函数最初由我的应用程序中的一个新虚拟页面调用时,我需要存储一个名为“extraData”的 JS 对象的内容。该函数的后续调用无权访问“extraData”,因此如果underscore.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

如何杀死um.globals.extraData并将其替换为um.grid.loadOrUpdate内部的某种闭包

编辑

这是“JavaScript Patterns”中的一些代码,它促使我提出这个问题:

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

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

2 回答 2

0

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

您可以通过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;
    };
};

然后你可以像这样调用你的函数,记住它会返回一个函数的引用:

var alpha = um.grid.loadOrUpdate(0, { "key": "alpha-value" });
var beta = um.grid.loadOrUpdate(0, { "key": "beta-value" });

当您调用alpha()or时, extrabeta()的值将通过闭包保留,因此无需保留对它的全局引用。

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

例子

但是,如果您尝试保留extra所有共享调用的单个实例,loadOrUpdate则最好使用以前的技术并将当前值存储为函数本身的属性,或范围内的任何其他位置的那个功能。

于 2013-05-30T22:54:09.307 回答
0

这种方法是你所追求的吗?

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

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

于 2013-05-30T03:48:35.003 回答