javascript - 用js闭包替换js命名空间的全局变量

标签 javascript namespaces closures global

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

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

这是当前版本的伪代码。所有代码都位于“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 模式”中的一些代码:

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

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

最佳答案

对我来说,不清楚您要通过闭包实现什么目标。闭包允许您将变量的状态封装在当前范围内,如果您尝试创建对象的各种实例,每个实例都有自己的 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()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

Example

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

关于javascript - 用js闭包替换js命名空间的全局变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16826572/

相关文章:

javascript - 字母数字的正则表达式,还允许附加字符

php - 拉取php数据,使用split分隔字符串中的逗号,将数据发布到div中使用ajax每3秒刷新一次

php - 有没有办法在 PHP 匿名函数中不捕获 $this?

function - 支持词法范围 ScriptBlock 参数(例如Where-Object)

javascript - 如果我不知道索引,如何循环遍历二维数组

javascript - 如何使用css和jquery选择图像后突出显示图像

zend-framework - Zend 如何管理命名空间?

namespaces - 在 Clojure 中,在 ns 宏中使用 require ... as 而不是 use... 在地道上是否正确

javascript - 理解 JavaScript 中的命名空间

swift - 如果未调用闭包,我如何使 XCTest 失败?