Существует обходной путь для имитации защищенных участников, когда вы публикуете их на некоторое время, а затем снова приватизируете.Я не большой поклонник этого, но это "решение".
Добавление защищенных членов
Разделение скрипта на несколько модулей является обычной и удобной практикой.Это значительно облегчает управление большой кодовой базой и позволяет экономить полосу пропускания, когда модули не всегда требуются.
Но что, если мы хотим обмениваться данными между различными модулями?Если мы сделаем эти данные общедоступными, мы потеряем преимущества конфиденциальности, но если мы сделаем их конфиденциальными, они будут доступны только одному модулю.Что нам действительно нужно, так это общие частные члены, и они известны как защищенные.
JavaScript не имеет защищенных членов как таковых, но мы можем эффективно создавать их, временно делая данные общедоступными.Для этого позвольте мне сначала познакомить вас с двумя ключевыми функциями - расширением и приватизацией - которые мы определим как часть объекта служебных функций:
var utils = {
extend : function(root, props) {
for(var key in props) {
if(props.hasOwnProperty(key)) {
root[key] = props[key];
}
} return root;
},
privatise : function(root, prop) {
var data = root[prop];
try { delete root[prop]; } catch(ex) { root[prop] = null; }
return data;
}
};
Функция расширения просто добавляет новые свойства вобъект, в то время как функция приватизации копирует свойство, а затем удаляет оригинал.Мы можем использовать расширение в одном модуле, чтобы создать общедоступную ссылку на частную переменную, а затем использовать приватизацию в другом модуле, чтобы скопировать ее обратно в частную переменную и удалить общедоступную ссылку.
Итак, вот примерпервый модуль, который имеет два защищенных члена (включая сам объект utils) и один открытый член.Короче говоря, пример кода: служебные функции - это просто пустые оболочки, но они будут идентичны функциям, которые я вам показывал недавно:
var MyModule = (function() {
var myProtectedData = 909;
var utils = {
extend : function(root, props) { },
privatise : function(root, prop) { }
};
this.myPublicData = 42;
return utils.extend(this, { myProtectedData : myProtectedData, utils : utils });
})();
Вы можете видеть, как мы используем вариантшаблон разоблачающего модуля, чтобы возвращать не только открытых членов, но и защищенных членов.Итак, на данный момент у нас есть три открытых члена: MyModule.myProtectedData, MyModule.utils и MyModule.myPublicData.
Теперь вот пример последнего модуля, который использует функцию приватизации для копирования указанных открытых членов обратно в приватныйпеременных, а затем удалите их общедоступные ссылки:
var MyModule = (function() {
var myProtectedData = this.utils.privatise(this, 'myProtectedData');
var utils = this.utils.privatise(this, 'utils');
return this;
}).apply(MyModule);
И как только это будет сделано, защищенные члены заблокированы внутри своих объектов, доступны для обоих модулей, но больше не доступны извне.
Обратите внимание, что функция приватизации полагается на наличие отдельных аргументов для объекта и ключа свойства, поскольку объекты в JavaScript передаются по ссылке.Таким образом, root является ссылкой на MyModule, и когда мы удаляем из него свойство, указанное ключом, мы удаляем это свойство из ссылочного объекта.
Но если это так:
privatise : function(root) {
var data = root;
try { delete root; } catch(ex) { root = null; } return data;
}
И вызывается так:
var myProtectedData = this.utils.privatise(this.myProtectedData);
Тогда публичные члены не будут удалены - функция просто удалит ссылку, а не свойство, на которое она ссылается.
Try... конструкция catch также необходима для более старых версий IE, в которых удаление не поддерживается.В этом случае мы аннулируем публичное свойство, а не удаляем его, что, очевидно, не то же самое, но имеет эквивалентный конечный результат отрицания публичной ссылки члена.