2013-05-30 46 views
2

更換名稱空間的全局變量JS我有一些在當前使用「全局」命名空間存儲的參數作爲全局變量單頁面的Web應用程序共享代碼與JS關閉

使用一個命名空間是在污染全局的「窗口」對象的改進,但似乎這樣的代碼是一個很好的候選人封閉堅持調用之間的值。我搞砸了一些想法,但似乎無法獲得關閉權的語法。

下面是當前版本的僞碼。所有的代碼都在「um」命名空間中。當我的共享函數最初由我的應用程序中的新虛擬頁面調用時,我需要存儲名爲'extraData'的JS對象的內容。該函數的後續調用沒有獲得「而額外」,所以我目前將其存儲在「um.globals.extraData」如果underscore.js確定該參數是一個對象。

//*************************** 
// 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 

回答

0

對我來說,目前還不清楚你試圖通過封鎖達到的目標。閉包允許你在當前範圍內封裝變量的狀態,如果你試圖創建對象的各種實例,每個實例都有自己的狀態,這可能會很方便。

你可以通過在返回到以後可以調用的函數的引用這樣一種方式實現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()中,價值額外將通過關閉保留,因此沒有必要保持全球參考。

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

不過,如果你試圖保持extra單個實例,爲loadOrUpdate共享所有來電,你可能會更好使用以前的技術,只是存儲電流值作爲函數本身的屬性,或者該函數範圍內的任何其他位置。

+0

我開始認爲擺脫我的命名空間'全局'可能不是'loadOrUpdate 」。正如你所提到的,我只需要一個「loadOrUpdate」實例,原始實現很好。 'um.globals ...'中的值不會污染窗口名稱空間,而名稱'globals'則清楚地表明存儲在其中的任何值都旨在全局範圍內'um ...'我認爲這是一種情況試圖過度優化或過度設計已經運行良好的東西。全局變量本質上不是邪惡的。 :-) –

+0

同意,這聽起來像你有什麼好.. –

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 

我已經在周圍(在這種情況下窗口)範圍範圍的一個匿名函數內部的全局變量,並提供在該函數中聲明的函數的對象上 - 所以它可以訪問'globals'變量,但它在外面不可見。

+0

它*看起來像你的實現仍然非常接近我的'ns.func'之外的全局變量被用來捕獲'opts'。我將用來自「Javascript Patterns」的封閉示例更新我的原始問題,該示例最初使我認爲內聯閉包是消除全局變量的方法。 –

+0

是不是一樣 - 在函數範圍內隱藏一個變量?在我的例子中,變量'globals'在全局範圍中不可見。這個名字很糟糕,但是我保留這個名字以表明它在原始示例中的用途。變量'globals'隱藏在匿名函數的作用域中。 – sync

+0

這裏有一個參考,以防術語混淆(我只是自己查看它!):「內部函數引用其外部函數的局部變量創建閉包」http://robertnyman.com/2008/10/09/explaining- javascript-scope-and-closures/...這就是我的例子,一個由內部函數引用的變量,範圍在外部函數中,在全局範圍內不可見。類似於Crockford的私有變量實現IIRC。 – sync