2013-05-30 1 views
2

У меня есть некоторые общий код в веб-приложения в одной страницы, что в настоящее время с помощью «GLOBALS» пространства имен для хранения параметра в качестве глобальной переменной.Заменить JS пространств имён глобальная переменная с Js закрытия

Использование пространства имен является улучшением по сравнению с загрязнением глобального объекта «окна», но похоже, что этот код является хорошим кандидатом на закрытие, чтобы сохранить значение между вызовами. Я перепутал некоторые идеи, но, похоже, не могу получить синтаксис для права закрытия.

Вот псевдокод текущей версии. Весь код находится внутри пространства имен «um». Когда моя общая функция изначально вызывается новой виртуальной страницей в моем приложении, мне нужно сохранить содержимое объекта JS с именем «extraData». Последующие вызовы функции не имеют доступа к «extraData», поэтому я в настоящее время храню ее в «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?

EDIT

Вот некоторые из кода "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 

ответ

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() или 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 ...' НЕ загрязняют пространство имен в окнах, а имя «глобальные переменные» дает понять, что любые значения, хранящиеся в нем, предназначены для глобального охвата внутри «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/... Это то, что у меня есть в моем примере, переменная, на которую ссылается внутренняя функция, ограниченная внешней функцией, невидимая в глобальном масштабе. Подобно частной реализации ChRC Crockford IIRC. – sync

Смежные вопросы