В чем разница между (function() {/*.....*/})(); и (function ($) {/*.....*/}) (jQuery);
Есть ли разница между:
(function() {
/*..........*/
})();
и:
(function($) {
/*..........*/
})(jQuery);
Ответы
Ответ 1
Другие люди объяснили, в чем разница, но не почему вы используете последний.
Переменная $
чаще всего используется jQuery. Если у вас есть тег script, который загружает jQuery, а другой, который загружает ваш код, он отлично работает. Теперь бросьте prototype.js в микс. Если вы загрузите prototype.js, а затем jQuery, $будет по-прежнему jQuery. Сделайте это по-другому, а теперь $- prototype.js.
Если вы пытались использовать $
на такой странице, вы, вероятно, получите ошибки или странное поведение.
В StackOverflow есть много вопросов по этой проблеме. Плагины не должны много думать о загружаемой странице, поэтому они используют этот шаблон в обороне.
Ответ 2
Я спрашиваю, есть ли разница между (function() {/.../})(); и (функция ($) {/.../}) (jQuery);
Небольшая разница. В случае (function($){/*…*/})(jQuery);
и отсутствия jQuery вы сразу же получите сообщение об ошибке после загрузки страницы. Это проще обнаружить jquery absense или неправильный порядок включения скриптов, когда код jquery включен в jQuery.
В случае (function(){/*…*/})();
вы получите сообщение об ошибке, когда код внутри этой конструкции фактически вызывает один из методов jQuery. Сложнее обнаружить эту ошибку, но с другой стороны вы можете включить ваши jquery-скрипты перед jquery.
Я предпочитаю первый случай.
Ответ 3
Вторая форма (function($){/*…*/})(jQuery);
может быть немного безопаснее при работе в среде, где вы не выполняете (или не можете) строгое соблюдение кода, который будет помещен на ваш сайт.
Раньше я работал на большом сайте с большим количеством сторонних объявлений. Эти объявления часто неспешно вводили свою собственную версию jQuery, и иногда они переопределяли глобальный объект $
jQuery. Таким образом, в зависимости от того, как мы написали наш код, мы могли бы называть методы, которые больше не существовали или имели немного отличающееся поведение от ожидаемого. Это невозможно отладить, поскольку некоторые объявления никогда не появятся в нашей области или не будут исключены из нашей среды. Это означало, что мы должны были чрезвычайно защищать сферу действия, вводить наши зависимости до того, как какой-либо рекламный код имел возможность загружать, пространство имен, которое должно было быть глобальным, и не молиться без рекламы.
Ответ 4
Другие ответы довольно фрагментированы, поэтому я хотел бы дать более подробный ответ на вопрос.
Главный вопрос может быть ответом, если вы понимаете.
Что означает (function(argument){ /*...*/ })(value);
?
Это быстрая ручная версия:
var tempFunction = function(argument){
/* ... */
}
tempFunction(value);
Без необходимости преодолевать стычки вызывать новое ужасное имя для функции, которую вы только однажды назовете и забудете. Такие функции называются anonymous function
, так как им не присвоено имя.
Итак, (function(){/*...*/})()
создает функцию, которая не принимает аргумент и выполняет его немедленно, а (function($){/*...*/})(jQuery)
создает функцию, которая принимает один аргумент с именем $
, и присваивает ему значение jQuery
.
Теперь, когда мы знаем, что означает выражение, безусловно, первое, что думает о нашем уме,
"Почему?". Уже не $
jQuery
Ну, не совсем. Мы никогда не сможем быть уверены. $
является псевдонимом jQuery
, но другие библиотеки также могут использовать один и тот же псевдоним. Как пользователь @FakeRainBrigand уже указал в его ответ, prototype.js также использует $
в качестве своего псевдонима. В таких случаях, когда какая-то библиотека присваивает свое значение $
, выигрывает позже.
Практика (function($){...})(jQuery)
очень похожа на импорт псевдонима на других языках программирования. Вы явно сообщаете системе, что ваша функция:
- Требуется объект/библиотека с именем
jQuery
и
- В вашей функции
$
означает jQuery
.
Таким образом, даже если кто-то включает новую библиотеку позже, которая переопределяет псевдоним $
на глобальном уровне, ваш плагин/фреймворк все еще работает по назначению.
Поскольку javascript настолько... "гибкий" в присваивании переменных, некоторые люди (включая меня) идут так же, как делать такие вещи, как
var myApplication = (function($, undefined){ ... })(jQuery);
Примените одно и то же понимание, легко интерпретировать вторую часть аргумента как: не присваивать значение переменной undefined
. Поэтому мы можем быть уверены, что даже если какой-то идиот присвоит значение undefined
позже, наш if(checkVariable === undefined){}
не сломается. (это не миф, люди действительно присваивают значения undefined
)
Когда он обычно используется в javascript?
Эта практика анонимных функций чаще всего обнаруживается в процессе предоставления инкапсуляции для вашего плагина/библиотеки.
Например:
var jQuery = (function(){
var publicFunction = function(){ /* ... */}
var privateFunction = function(){ /* ... */}
return {
publicFunction : publicFunction
}
})();
При этом в глобальной области отображается только jQuery.publicFunction()
, а privateFunction()
остается закрытым.
Но, конечно, он также используется в любое время, когда вы просто хотите создать функцию, немедленно вызвать ее и выбросить. (Например, как обратный вызов для асинхронной функции)
За бонусный вопрос
почему они использовали (function(){}()
дважды в приведенном ниже коде?
Ну, скорее всего, потому что они не знают, что делают. Я не могу думать о какой-либо причине помещать вложенную функцию таким образом. Ничего.
Ответ 5
(function(){/*...*/})();
не устанавливает $
в качестве ссылки на jQuery
в пределах IIFE и (function($){/*...*/})(jQuery);
устанавливает $
или другое имя параметра; например.; (function(Z){/*...* Z("body") where Z : jQuery*/})(jQuery);
в качестве ссылки на jQuery
в пределах IIFE
Ответ 6
Они оба закрыты. Первая - это анонимная функция, которая будет немедленно сбрасывать любой хорошо отформатированный код. Второй - закрытие jQuery. Так как библиотека jQuery инициирует ее, она обертывает свой код в объекте JQuery и предоставляет, что это не символ $.
(function(){}()) // this is a closure
(function($){}(jQuery)) // is a closure that wraps the executed code inside of the jQuery returned object and exposes it via the $.
Ответ 7
При этом (function(){/*…*/})();
вы не передаете какой-либо аргумент внутренней функции, а при этом (function($){/*…*/})(jQuery);
вы передаете jQuery
в качестве аргумента во внутреннюю функцию и ожидаете, что ее значение будет $
(что означает, вы сможете использовать jQuery
внутри внутренней функции).
Пример:
(function($){
$(document).ready(function() {
console.log('all resources loaded');
})
})(jQuery);
Ответ 8
Они оба являются примерами Immediately Invoked Function Expression
. В этом смысле нет разницы между (function(){/*…*/})();
и (function($){/*…*/})(jQuery);
. Таким образом, никаких преимуществ не получается, обертывая (function($){/*…*/})(jQuery);
внутри (function(){/*…*/})();
При выполнении функции создается новый контекст выполнения. Поэтому, когда выполняется (function(){/*…*/})();
, создается контекст. Опять же, когда выполняется (function($){/*…*/})(jQuery);
, создается другой контекст. Поскольку первый контекст не используется (т.е. В нем не объявлены никакие переменные), я не вижу никаких преимуществ, полученных в результате обертывания.
(function() { // <-- execution context which is not used
(function($) { // <-- another execution context
"use strict";
/*..........*/
})(jQuery);
})();