Имеет ли этот способ определения объектов JS какую-либо цель?
Я поддерживаю некоторый устаревший код, и я заметил, что используется следующий шаблон для определения объектов:
var MyObject = {};
(function (root) {
root.myFunction = function (foo) {
//do something
};
})(MyObject);
есть ли смысл в этом? Это эквивалентно просто делать следующее?
var MyObject = {
myFunction : function (foo) {
//do something
};
};
Я не собираюсь вступать в священный поиск, чтобы рефакторинг всей кодовой базы на мои симпатии, но я действительно хотел бы понять причину этого Окольного способа определения объектов.
спасибо!
6 ответов:
это называется модуль pattern http://toddmotto.com/mastering-the-module-pattern/
основная причина для вас, чтобы создать действительно частные методы и переменные. В вашем случае, это не имеет смысла, потому что он не скрывает никаких деталей реализации.
вот пример, где имеет смысл использовать шаблон модуля.
var MyNameSpace = {}; (function(ns){ // The value variable is hidden from the outside world var value = 0; // So is this function function adder(num) { return num + 1; } ns.getNext = function () { return value = adder(value); } })(MyNameSpace); var id = MyNameSpace.getNext(); // 1 var otherId = MyNameSpace.getNext(); // 2 var otherId = MyNameSpace.getNext(); // 3
в то время как если бы вы просто использовали прямой объект,
adder
иvalue
станет публикаvar MyNameSpace = { value: 0, adder: function(num) { return num + 1; }, getNext: function() { return this.value = this.adder(this.value); } }
и вы могли бы сломать его, делая такие вещи, как
MyNameSpace.getNext(); // 1 MyNameSpace.value = 0; MyNameSpace.getNext(); // 1 again delete MyNameSpace.adder; MyNameSpace.getNext(); // error undefined is not a function
но с версией модуля
MyNameSpace.getNext(); // 1 // Is not affecting the internal value, it's creating a new property MyNameSpace.value = 0; MyNameSpace.getNext(); // 2, yessss // Is not deleting anything delete MyNameSpace.adder; MyNameSpace.getNext(); // no problemo, outputs 3
цель состоит в том, чтобы ограничить доступность функции в закрытие, чтобы помочь предотвратить другие скрипты от выполнения кода на нем. Обернув его вокруг закрытие вы переиначивая scope выполнения для всего кода внутри закрытие и эффективно создает частную область. См. эту статью для получения дополнительной информации информация:
http://lupomontero.com/using-javascript-closures-to-create-private-scopes/
из статьи:
одной из наиболее известных проблем в JavaScript является его зависимость от a глобальном уровне, который в основном означает, что любые переменные, которые вы объявляете вне функции живут в том же пространстве имен: зловещий объект Window. Из-за характера веб-страниц, многие скрипты из разные источники могут (и будут) работать на той же странице обмена общий глобальный охват, и это может быть действительно очень плохо, как это может привести к коллизиям имен (переменные с одинаковыми именами перезаписано) и вопросы безопасности. Чтобы минимизировать проблему, мы можем использовать Мощные замыкания JavaScript для создания частных областей, где мы можем убедитесь, что наши переменные невидимы для других скриптов на экране. страница.
код:
var MyObject = {}; (function (root) { function myPrivateFunction() { return "I can only be called from within the closure"; } root.myFunction = function (foo) { //do something }; myPrivateFunction(); // returns "I can only be called from within the closure" })(MyObject); myPrivateFunction(); // throws error - undefined is not a function
плюсы:
поддерживает переменные в отдельный объем.
можно расширить функциональные возможности существующего объекта.
повышение производительности.
Я думаю, что выше трех простых пунктов достаточно, чтобы следовать этим правилам. И чтобы сохранить его простым, его ничего, кроме написания внутренних функций.
в конкретном случае, который вы показываете, нет никакой существенной разницы, с точки зрения функциональности или видимости.
вполне вероятно, что исходный кодер принял этот подход в качестве своего рода шаблона, позволяющего ему определять частные переменные, которые могут быть использованы в определении таких вещей, как
myFunction
:var MyObject = {}; (function(root) { var seconds_per_day = 24 * 60 * 60; // <-- private variable root.myFunction = function(foo) { return seconds_per_day; }; })(MyObject);
это позволяет избежать расчета
, нет ничего принципиально отличного от этого и просто говорюseconds_per_day
каждый раз, когда функция вызывается, в то же время сохраняя его от загрязнения глобальной области.var MyObject = function() { var seconds_per_day = 24 * 60 * 60; return { myFunction: function(foo) { return seconds_per_day; } }; }();
исходный кодер, возможно, предпочел бы иметь возможность добавлять функции к объекту, используя декларативный синтаксис
root.myFunction = function
, а не синтаксис объекта/свойстваmyFunction: function
. Но это различие в основном зависит от предпочтений.однако структура, взятая исходным кодером, имеет то преимущество, что свойства / методы могут быть легко добавлены в другом месте код:
var MyObject = {}; (function(root) { var seconds_per_day = 24 * 60 * 60; root.myFunction = function(foo) { return seconds_per_day; }; })(MyObject); (function(root) { var another_private_variable = Math.pi; root.myFunction2 = function(bar) { }; })(MyObject);
итог, нет необходимости принимать этот подход, если вам это не нужно, но также нет необходимости его менять, поскольку он отлично работает и на самом деле имеет некоторые преимущества.
первый шаблон может быть использован в качестве модуля, который принимает объект и возвращает объект с некоторыми изменениями. Другими словами, вы можете определить такие модули следующим образом.
var module = function (root) { root.myFunction = function (foo) { //do something }; }
и использовать его как:
var obj = {}; module(obj);
так что преимущество может быть повторное использование этого модуля для последующего использования.
в первом шаблоне вы можете определить закрытая область для хранения личных такие вещи, как частные свойства и методы. Например, рассмотрим этот фрагмент кода:
(function (root) { // A private property var factor = 3; root.multiply = function (foo) { return foo * factor; }; })(MyObject);
этот шаблон можно использовать для добавления метода или свойства ко всем типам объектов, таких как массивы, объектные литералы, функции.
function sum(a, b) { return a + b; } (function (root) { // A private property var factor = 3; root.multiply = function (foo) { return foo * factor; }; })(sum); console.log(sum(1, 2)); // 3 console.log(sum.multiply(4)); // 12
на мой взгляд, главным преимуществом может быть второй (создание частного объема)
этот шаблон обеспечивает область, в которой можно определить вспомогательные функции, которые не видны в глобальной области видимости:
(function (root) { function doFoo() { ... }; root.myFunction = function (foo) { //do something doFoo(); //do something else }; })(MyObject);
doFoo
является локальным для анонимной функции, на нее нельзя ссылаться извне.