2015-05-07 2 views
1

Рассмотрят следующий contrived bit of JavaScript на основе revealing module pattern:Использования ECMAScript 5 получить/установить свойство с выявлением модуля шаблона

var RevealingModuleSample = function() { 
    var moduleName = "DefaultModuleName", 

    init = function (name) { 
     moduleName = name 
    }, 

    issueAlert = function() { 
     alert(moduleName + " module is running"); 
    } 

    return { 
     init: init, 
     issueAlert: issueAlert 
    }; 
}(); 

RevealingModuleSample.init("SampleModule"); 

RevealingModuleSample.issueAlert(); 

Есть ли способ превратить MODULENAME в собственность с методами получения и установками и есть те, методы getter/setter, вызванные внутренними ссылками на moduleName? Чтобы дать конкретный пример, рассмотрит следующее similarly contrived C# example:

public class ContrivedCsharpExample 
{ 
    private string _moduleName; 

    protected string moduleName 
    { 
     get { 
      // Perhaps some logging code here that records the moduleName was retrieved. 
      return this._moduleName; 
     } 
     set { 
      // Some code here that ensure that a valid moduleName was passed. 
      this._moduleName = value; 
     } 
    } 

    public void init(string moduleName) { 
     this.moduleName = moduleName; 
    } 

    public void issueAlert() { 
     Console.WriteLine(this.moduleName); 
    } 


    public static void Main() 
    { 
     var module = new ContrivedCsharpExample(); 

     module.init("SampleC#Module"); 
     module.issueAlert(); 
    } 
} 

Обратите внимание, что внутренне к классу, методы вызывают свойства, которые имеют геттер/сеттер. Это позволяет нам добавить дополнительный код внутри этих методов getter/setter, тогда как если бы мы использовали только свойства, доступные вне класса, методы «init» и «issueAlert» должны были бы непосредственно проверять поле и любую логику, которую мы добавили в геттер/сеттер будет обходить.

Проблема, которую я вижу, заключается в том, что в шаблоне раскрывающего модуля переменная «moduleName» не является свойством объекта - это просто переменная, которая в настоящее время находится в области видимости. Поэтому вы не можете просто вытащить его и заменить его парой get/set. Правильно?

There is a related question on StackOverflow, но в этом случае спрашивающий ищет способ возвращения объект с свойством с геттер/сеттер кода, так что внешние пользователи модуля имеют свой доступ к свойству маршрутизации с помощью методов Get/Set , Решение указано прямо в вопросе, но предоставленное решение не позволяет коду, находящемуся внутри модуля, получить доступ к этому свойству без непосредственной работы с переменной, минуя функции get/set.

Я думаю, что это просто невозможно с помощью раскрывающего шаблона модуля, это правильно? Есть ли способ иметь вызовы внутри модуля, направленные через функции get/set?

+0

Должен ли использоваться шаблон раскрывающейся модели? JavaScript использует ключевое слово 'this', если вы хотите. Для меня это не имеет значения. Я могу работать с этим. Это просто вопрос. – PHPglue

+0

Поскольку все эти функции модуля объявлены локально, в любом случае, получатели/сеттеры недоступны извне, и вы все равно должны вытащить ссылки на переменные, я бы рекомендовал заменить их на простые вызовы функций (а не на свойство accessor на надуманный объект). – Bergi

ответ

3

Вы правы, так как вы не можете определить setter/getter по переменной. Это должно быть свойство объекта. Затем раствор для преобразования внутренности вашего модуля в объект, в то же время подвергая тот же публичный API:

var RevealingModuleSample = function() { 
 

 
    var self = { 
 

 
     _moduleName: "DefaultModuleName", 
 

 
     set moduleName(name) { 
 
      console.log("setting module name: " + name); 
 
      self._moduleName = name; 
 
     }, 
 

 
     get moduleName() { 
 
      return self._moduleName; 
 
     }, 
 

 
     init: function (name) { 
 
      self.moduleName = name; 
 
     }, 
 

 
     issueAlert: function() { 
 
      alert(self.moduleName + " module is running"); 
 
     } 
 

 
    }; 
 

 
    return { 
 
     init: self.init, 
 
     issueAlert: self.issueAlert 
 
    }; 
 
}(); 
 

 
RevealingModuleSample.init("SampleModule"); 
 
RevealingModuleSample.issueAlert();

одним из последствий воздействия методов объекта, является контекст или при вызове методов теряется значение this. Следовательно, использование объекта self внутри объекта, что является просто ссылкой на this.

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

0

is Способ использования IIFE, чтобы приблизиться к тому, что вы хотите, хотя я думаю, что это слишком много. Тем не менее, вам придется пойти на компромисс - вместо того, чтобы использовать свойства, которые вы всегда должны использовать функции:

var Example = function() { 
    var moduleName = (function(moduleName){ 
    return function(value){ 
     if (val === undefined) return moduleName; 
     moduleName= val; 
    }; 
    })("DefaultModuleName"); 

    init = function (name) { 
     moduleName(name); 
    }, 

    issueAlert = function() { 
     alert(moduleName() + " module is running"); 
    } 

    return { 
     init: init, 
     issueAlert: issueAlert 
    }; 
}(); 

Example.init("SampleModule"); 

Example.issueAlert(); 

Хитрость заключается в том, чтобы использовать IIFE вернуть функцию доступа. Функция является getter, если вызывается без аргументов, и это setter, если он вызван с аргументом.Функция accessor изменяет значение скрытой переменной в закрытии IIFE, и нет доступа к чему-либо за пределами IIFE, кроме как через функцию accesor.

Показательный образец модуля - это красная селедка в этом случае - он не имеет ничего общего с вопросом, и это anti-pattern, так как это худший из implementations of the module pattern.