Навіщо визначати анонімну функцію і передавати їй jQuery як аргумент?


96

Я переглядаю чудовий демонстраційний код peepcode із скриншотів backbone.js. У ньому магістральний код укладений в анонімну функцію, яка передається об'єкту jQuery:

(function($) {
  // Backbone code in here
})(jQuery);

У своєму власному магістральному коді я щойно обернув весь свій код у події jQuery DOM 'готовий':

$(function(){
  // Backbone code in here
});

У чому сенс / перевага першого підходу? Роблячи це таким чином, створюється анонімна функція, яка потім виконується негайно з об’єктом jQuery, який передається як аргумент функції, фактично гарантуючи, що $ є об’єктом jQuery. Це єдиний сенс - гарантувати, що jQuery прив'язаний до '$', чи є інші причини для цього?


4
Натомість вам слід спочатку переглянути SO.
Олександр

Взаємодія з іншими бібліотеками - якщо автору сторінки потрібно використовувати $.noConflict(), перший приклад все одно буде працювати.
DCoder

Можливий дублікат: jQuery і $ questions
Олександр

Див. Можливий дублікат jQuery document.ready проти самовиклику анонімної функції для різниці
Бергі

@Alexander, але тоді інші люди знайдуть це питання насамперед. :-)
caiosm1005

Відповіді:


179

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

Модулі JavaScript


(function($) {
  // Backbone code in here
})(jQuery);

Це шаблон "Модуль JavaScript", реалізований із функцією негайного виклику.

Мета цього коду - забезпечити "модульність", конфіденційність та інкапсуляцію вашого коду.

Реалізація цієї функції є функцією, яка негайно викликається викликом (jQuery)дужок. Метою передачі jQuery в дужки є надання локального масштабування до глобальної змінної. Це сприяє зменшенню накладних витрат на пошук $змінної та дозволяє в деяких випадках покращити стиснення / оптимізацію мініфайєрів.

Функції, що викликаються негайно, виконуються, ну, негайно. Як тільки визначення функції завершено, функція виконується.

Функція jQuery "DOMReady"

Це псевдонім функції "DOMReady" jQuery: http://api.jquery.com/ready/


$(function(){
  // Backbone code in here
});

Функція jQuery "DOMReady" виконується, коли DOM готовий до маніпулювання вашим кодом JavaScript.

Модулі проти DOMReady в магістральному коді

Це погана форма для визначення коду Backbone всередині функції DOMReady jQuery, що може призвести до шкоди для продуктивності вашої програми. Ця функція не викликається, поки DOM не завантажується і не готова до маніпуляцій. Це означає, що ви чекаєте, поки браузер хоча б раз не проаналізує DOM, перш ніж ви визначатимете свої об’єкти.

Краще визначити об’єкти Backbone поза функцією DOMReady. Я, серед багатьох інших, вважаю за краще це робити в шаблоні модуля JavaScript, щоб я міг забезпечити інкапсуляцію та конфіденційність свого коду. Я схильний використовувати шаблон "Модуль розкриття" (див. Перше посилання вище), щоб забезпечити доступ до бітів, які мені потрібні поза мого модуля.

Визначаючи ваші об'єкти поза функцією DOMReady та надаючи певний спосіб посилання на них, ви дозволяєте браузеру отримати початок обробки вашої JavaScript, що потенційно прискорить користувацький досвід. Це також робить код більш гнучким, оскільки ви можете переміщати речі, не турбуючись про створення більше DOMREady функцій під час переміщення речей.

Ви, швидше за все, скористаєтесь функцією DOMReady, навіть якщо ви визначите свої об'єкти Backbone де-небудь ще. Причина полягає в тому, що багатьом програмам Backbone потрібно якось маніпулювати DOM. Для цього вам потрібно зачекати, поки DOM буде готовий, тому вам потрібно використовувати функцію DOMReady для запуску програми після її визначення.

Ви можете знайти безліч прикладів цього в Інтернеті, але ось дуже основна реалізація, використовуючи як модуль, так і функцію DOMReady:



// Define "MyApp" as a revealing module

MyApp = (function(Backbone, $){

  var View = Backbone.View.extend({
    // do stuff here  
  });

  return {
    init: function(){
      var view = new View();
      $("#some-div").html(view.render().el);
    }
  };

})(Backbone, jQuery);



// Run "MyApp" in DOMReady

$(function(){
  MyApp.init();
});

1
Дякую за цю детальну відповідь. Я знав про функцію DOMReady, яка телефонує лише тоді, коли спрацьовує подія готовності DOM, але ніколи не думав, що це може бути проблемою. Розщеплення коду на визначення бітів основи всередині модуля, а потім взаємодія з ними в домі готовий насправді здається найкращим підходом
Метт Робертс

2
Цікаво, що прикладний додаток "todo" з магістральним src все готове до дому.
Метт Робертс,

2
Не забувайте, шаблон модуля javascript також називається IIFE.
Джесс

1
анонімні функції по суті виконуються одночасно з готовністю до DOM, то як це робить їх більш ефективними ??
bhavya_w

14

Як незначний сиденот, надсилання $ як аргументу анонімній функції робить $ local для тієї функції, яка має невелике позитивне значення для продуктивності, якщо функцію $ називають багато. Це пов’язано з тим, що javascript спочатку здійснює пошук змінних у локальній області, а потім переходить вниз до області вікна (де зазвичай живе $).


9

Це гарантує, що ви завжди можете використовувати $всередині цього закриття, навіть якщо воно $.noConflict()було використано.

Без цього закриття ви б мали використовуватись jQueryзамість $цілого часу.


4

Це уникнути потенційного конфлікту змінної $. Якщо щось інше визначає змінну на ім’я $, ваш плагін може використовувати неправильне визначення

Зверніться до http://docs.jquery.com/Plugins/Authoring#Getting_Started для отримання більш докладної інформації


2

Використовуйте обидва.

Функція самовиклику, в якій ви передаєте jQuery, щоб запобігти конфліктам бібліотек і просто переконатися, що jQuery доступний, як і слід було очікувати з $.

І метод ярлика .ready (), необхідний для запуску JavaScript лише після завантаження DOM:

(function($) {
    $(function(){
          //add code here that needs to wait for page to be loaded
    });

    //and rest of code here
})(jQuery);

Коротшу версію, яку я знайшов в іншому місці на SO (також захищає невизначену) :jQuery(function ($, undefined) { /* Code */ });
Джаред Готте
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.