Есть ли разница между этими двумя шаблонами JavaScript? - PullRequest
8 голосов
/ 02 февраля 2011

Глядя на некоторые библиотеки JavaScript и код других людей, я видел два общих шаблона, я не знаю, есть ли разница или преимущество в использовании одного из них.Шаблоны выглядят примерно так:

1.

var app = (function () {
    // Private vars

    // Module
    var obj = {
        prop: "",
        method: function () {}
    };

    return obj;
})();

2.

(function () {
    // Private vars

    // Module
    var obj = {
        prop: "",
        method: function () {}
    };

    window.app = obj;
})();

Являются ли эти шаблоны одинаковыми или один из них имеет преимущество илиотличается от других?

Заранее спасибо.

Ответы [ 5 ]

5 голосов
/ 02 февраля 2011

Второй предполагает существование объекта с именем window в родительской области и присваивает ему свойство.

Первый оставляет его вызывающей стороне для выполнения назначения и не зависит отwindow определяется (это, вероятно, только внутри веб-браузера).

Итак, я бы сказал, что первый определенно лучше (более автономный, менее зависимый от окружающей среды).

2 голосов
/ 02 февраля 2011

tl; dr: выберите один метод и будьте последовательны .


На мой взгляд, первый метод имеет небольшое преимущество для удобочитаемости. В моей голове, когда я читаю его, я вижу, что «модуль app определяется» и что все внутри этого замыкания принадлежит этому модулю. Это естественное разложение для меня и навязывает объектно-ориентированную природу модуля, который должен быть определен.

Еще одна причина, по которой я предпочитаю первый метод, заключается в том, что более разумно изменить область, в которой определен модуль. Каждый модуль, который вы определяете, не должен быть частью глобальной области видимости. Используя второй метод, если область не вводится путем передачи родительского объекта, как иллюстрирует Джаред Фарриш на своем примере jQuery, тогда вы рискуете сломать свой код, если решите изменить имя этот родительский объект. Этот пример иллюстрирует точку:

var namespace = {
  subns: { ... }
};

(function() {
  var module = { ... };
  namespace.subns.someModule = module;
}());

Каждый раз, когда идентификаторы namespace или subns меняются, вам также необходимо обновить этот модуль и любой другой модуль, который следует этому шаблону, и добавляет себя к тому же объекту.

В общем, ни один метод, ни второй метод (с внедрением зависимости) не "лучше", чем другой, это просто вопрос предпочтений. Единственное преимущество, которое может принести это обсуждение, заключается в том, что вы должны выбрать один метод и быть последовательными .

1 голос
/ 02 февраля 2011

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

Один не является более "жестко запрограммированным", чем другой, поскольку ни один из них не занимается созданием прототипов функций, в которых можно создавать клоны объекта с помощью ключевого слова new.На мой взгляд, это просто вопрос предпочтений.

Например, jquery делает что-то похожее на последнее:

(function( window, undefined ) {

// Use the correct document accordingly with window argument (sandbox)
var document = window.document;
var jQuery = (function() {

// Define a local copy of jQuery
var jQuery = function( selector, context ) {
        // The jQuery object is actually just the init constructor 'enhanced'
        return new jQuery.fn.init( selector, context, rootjQuery );
    },

    // Map over jQuery in case of overwrite
    _jQuery = window.jQuery,

    // Map over the $ in case of overwrite
    _$ = window.$,

...

Но библиотека JS Prototype делает первое:

var Prototype = {
  Version: '1.6.1',

  Browser: (function(){
    var ua = navigator.userAgent;
    var isOpera = Object.prototype.toString.call(window.opera) == '[object Opera]';
    return {
      IE:             !!window.attachEvent && !isOpera,
      Opera:          isOpera,
      WebKit:         ua.indexOf('AppleWebKit/') > -1,
      Gecko:          ua.indexOf('Gecko') > -1 && ua.indexOf('KHTML') === -1,
      MobileSafari:   /Apple.*Mobile.*Safari/.test(ua)
    }
  })(),

...

Я не знаю ни одногопричина, по которой один лучше другого или что они выполняют свою задачу по-другому (для создания объекта приложения в пространстве имен окна).

0 голосов
/ 02 февраля 2011

В первом примере, если app определено в другой функции, app будет доступно только в этой локальной области, тогда как во втором примере переменная app явно назначена глобальной области.

Во втором примере app будет назначаться только глобальной области, если она определена в глобальной области за пределами функций.

0 голосов
/ 02 февраля 2011

Вторая форма имеет небольшое преимущество в том, что у вас есть полностью автономная функция;например, вы могли бы тогда иметь стандартный заголовок и нижний колонтитул для ваших файлов JS.

Часть, по которой я не полностью продан, является локальной переменной внутри блока.Я предпочитаю предпочитать это:

(function () {
   // Private vars

   // Module
   window.app = {
       prop: "",
       method: function () {}
   };
})();

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...