2013-11-18 5 views
2

Я видел этот синтаксис для создания анонимной функции конструктора в JavaScript:JavaScript Анонимный конструктор Функция:! Function() {}();

var Application = Application || {}; 
!function(window, Application) { 
    Application.property = {/*...*/} 
    Application.method = function(){/*...*/} 
}(window, Application); 

Я хочу понять, что следующие части здесь:

  1. Что такое преимущество использования первой линии (т.е. var o = o || {};) vs только указывая var o = (function(){})();?
  2. Почему ! используется перед функцией?
  3. Зачем пропускать window или Application в качестве параметров, когда они являются глобальными объектами?
  4. Это самый удобный способ для анонимной функции конструктора и как это лучше, чем:

4а)

var Application = { 
    property: {}, 
    method: function(){} 
} 

или 4b)

var Application = (function() { 
    var method = function(){/*...*/} 
    return {method:method}; 
}()); 
+0

он не лучше вашего альтернативного кода. Я бы сказал, что это хуже. – akonsu

+0

Это смешно, но почему? – Vad

+0

2 фрагмента не эквивалентны. '! function() {}()' используется вместо '(function() {})()', см. [этот вопрос] (http://stackoverflow.com/questions/3755606/what-does-the- восклицательный знак-do-before-the-function) для деталей. – Vatev

ответ

0

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

Комментарий от Ватева объясняет, что делает !.Это еще один синтаксис для того, чтобы данная функция стала самоисполняемой анонимной функцией. (Кстати, он также принимает возвращаемое значение функции, которое в настоящее время undefined, и переворачивает его правдоподобие, поэтому оно оценивается как истинное. Так как результат не сохраняется в любой переменной, это явно не является целью.)

Зачем нужны функции window и Application? Это функция безопасности, если другие изменения кода window или Application позже. Это гарантирует, что в анонимной функции window и Application - это именно то, что вы ожидаете от нее. В приведенном ниже сокращенном примере это может показаться нецелесообразным - в конце концов, зачем защищать эти переменные, если вы используете их немедленно и не сохраняете их? Во многих случаях вы возвращаете что-то из этой функции, а затем window и Application будут храниться в закрытии, поэтому вы сохраните переменные. Это делает его безопасным от людей, которые позже решили сказать Application = {...}.

+0

«Причина безопасности» - не большая причина: если значение перезаписывается, оно перезаписывается - период. Единственное значение, в котором вы можете защитить себя, - это «undefined», указав его как параметр, но ничего не пропуская (требуется только для старых браузеров, которые разрешают перезаписывать 'undefined'). Помимо этого, глобальные объекты сглаживания полезны для минимизации. –

+1

@ IngoBürk Если вы передадите 'Приложение' в функцию и сохраните ее в закрытии и вне закрытия, скажем,' Application = "hello" ', в пределах закрытия' Application' будет по-прежнему указывать на исходный объект. –

+0

Да, но внешний код все равно может перезаписать его, если, например, вызывается 'Application =" Foo "' перед вызовом IIFE. Конечно, это * - причина, но это не безупречно. Наверное, я был неясно, извините. –

0

Я не знаю, все ответы, но я постараюсь ответить, что смогу.

  1. Использование var Application = Application || {}; просто означает, что вы имеете дело с областью. Если переменная «Приложение» уже определена, это будет означать, что она наследуется и теперь доступна в текущей области. Если нет, то "||" part (означает OR) означает, что он будет создан как пустой объект. Вы имеете дело с созданием объекта, а затем воздействием на него, а не только с возвратом результата. Вот почему вы не должны использовать «o = (function() {...});». «o» будет результатом функции, а не объекта.

  2. Использование функции «!» Приводит к тому, что оно рассматривается как выражение, но это может быть сложно, потому что вам, возможно, придется думать в противоположностях. Например. ! null означает, что вы проверяете, что он не является нулевым, а не то, что вы проверяете его как null.

  3. Передача в окне, а также Объекты приложения имеют дело с прицелом, снова. Он явно передает их в функцию, а затем возвращает их в конце. Подумайте об этом, одевая одежду в стиральную машину. Вы вставляете их, что-то может случиться, а затем вы их получите. Это очень грубая идея, и это не лучший пример, но я подумал об этом некоторое время назад. Вы вставляете одежду, затем вызываете функцию полоскания, затем функцию мыла, затем снова промывайте, затем вращайте для слива воды.

  4. Надеюсь, кто-то может ответить на это, я не уверен, в чем отличия.

+0

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

0

С двух ответов до сих пор безнадзорных эти две детали: шаблон, используемый библиотеки, как JQuery использует следующие два параметра:

(function (window, undefined) { 
    window.myPlugin = ...; 
})(window); 

Есть две вещи, здесь происходит:

  • undefined указан как параметр, но не передан. Таким образом, undefined гарантированно имеет ожидаемое значение во внутренней области. Это необходимо только для старых браузеров, которые допускают перезапись undefined (хотя это всегда считалось плохой практикой - это именно то, что библиотеки, такие как jQuery, чтобы избежать другого кода, мешающего их коду).

  • Смещение глобального объекта, такого как window в пределах области действия, позволяет еще более минимизировать код (также работает для undefined). Очевидно, что чем больше ссылок у вас будет на объекты с псевдонимом, тем больше вы сэкономите:

.

(function(w,u){w.myPlugin=...;w.somethingElse=...;if(whatever===u){return;}})(window); 

по сравнению с

(function(){window.myPlugin=...;window.somethingElse=...;if(whatever===undefined){return;}})(); 

Вы не сэкономите много с window, так как, как правило, вы не хотите загромождать глобальный объект в любом случае. Но aliasing undefined может сэкономить вам довольно много места.

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