Чому “$ (). Ready (handler)” не рекомендується?


88

На сайті документації jQuery API дляready

Усі три наступні синтаксиси еквівалентні:

  • $ (документ) .ready (обробник)
  • $ (). готовий (обробник) (це не рекомендується)
  • $ (обробник)

Після домашнього завдання - читання та гри з вихідним кодом , я не уявляю, чому

$().ready(handler) 

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

rootjQuery = jQuery(document);
...
...

// HANDLE: $(function)
// Shortcut for document ready
} else if ( jQuery.isFunction( selector ) ) {
    return rootjQuery.ready( selector );
}

Але функція готовості не взаємодіє з селектором вибраних елементів вузла, readyвихідним кодом:

ready: function( fn ) {
    // Attach the listeners
    jQuery.bindReady();
        // Add the callback
    readyList.add( fn );
        return this;
},

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

Люблю:

  • штатний селектор: $('a').ready(handler) DEMO
  • Селектор нонсенсу : $('fdhjhjkdafdsjkjriohfjdnfj').ready(handler) DEMO
  • Невизначений селектор: $().ready(handler) DEMO

Нарешті ... на моє запитання: Чому $().ready(handler)не рекомендується?


60
@ChaosPandion: Мені здається, що він прагне зрозуміти інструменти, якими він користується, як тильну руку. Я б точно не назвав це марно витраченим зусиллям.
Джон

5
Хороше питання. Якщо комусь цікаво, ось порівняння продуктивності ... яке показує (принаймні в Chrome), що "нерекомендована" версія насправді найшвидша.
Джеймс Аллардіка,

5
Краще питання - чому вони взагалі взагалі існують, це має бути статичний метод ( $.readyнаприклад) і не вимагати спочатку побудови об’єкта jQuery.
Esailija

2
@Esailija робить найкраще з усіх. Якщо jQuery не планує надати якусь .ready()можливість для окремих елементів, не повинно бути жодних причин для побудови об’єкта jQuery.

2
@ChaosPandion. Ви не можете використовувати це ... $.readyвже взяте внутрішньою функцією jQuery, знайдіть вихідний код ready:.
gdoron підтримує Моніку

Відповіді:


88

Я отримав офіційну відповідь від одного з розробників jQuery:

$().ready(fn)працює лише тому, що $()раніше був ярликом до $(document) (jQuery <1.4)
Так $().ready(fn)був і читабельний код.

Але люди звикли робити такі речі, як $().mouseover()і всілякі інші божевілля.
і люди повинні були зробити, $([])щоб отримати порожній об’єкт jQuery

Отже, в 1.4 ми змінили його, так що він $()дає порожній jQuery, і ми щойно зробили$().ready(fn) роботу, щоб не зламати багато коду

$().ready(fn) буквально зараз просто виправлений в основному, щоб він працював належним чином для спадкової справи.

Найкраще місце для readyфункції $.ready(fn), але це справді давнє дизайнерське рішення, і це те, що ми маємо зараз.


Я запитав його:

Ви вважаєте, що $ (fn) читабельніше, ніж $ (). Готовий (fn)?!

Його відповідь була:

Я завжди роблю $ (document) .ready (fn) у реальних програмах, і, як правило, у програмі є лише один готовий блок документа, це не зовсім схоже на те, що стосується обслуговування.

Я думаю, що долар (fn) теж досить нечитабельний , це просто річ, про яку ви повинні знати, працює ™ ...


1
Має сенс, jQuery досить серйозно ставиться до зворотної
порівняльності

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

3
@gdoron +1 за те, що він дістався прямо з пащі коня.

2
@gdoron +1 для отримання реальної відповіді. І так, ми були досить близькі у своєму сприйнятті.
VisioN

" це просто річ, про яку ти повинен знати, що працює ™ ..." Ну так $(selector[, context])і є $(html[, ownerDocument]). Насправді ви можете просто використовувати jQuery()замість того, $()якщо проблема в тому, щоб знати, що це працює. Або навіщо взагалі використовувати jQuery?
JAB,

11

Оскільки різні варіанти виконують майже те саме, на що ви вказуєте, настав час надіти шапку для бібліотечного письменника та зробити деякі здогади.

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

  2. Набагато більш практична причина: друга версія - це єдина версія, яка не закінчується загортанням document, тому її легше зламати, підтримуючи код. Приклад:

    // BEFORE
    $(document).ready(foo);
    
    // AFTER: works
    $(document).ready(foo).on("click", "a", function() {});
    

    Порівняйте це з

    // BEFORE
    $().ready(foo);
    
    // AFTER: breaks
    $().ready(foo).on("click", "a", function() {});
    
  3. Пов’язане з вищезазначеним: readyє виродком у тому сенсі, що це (єдиний?) Метод, який буде працювати однаково незалежно від того, що обертається об’єкт jQuery (навіть якщо він нічого не обертає, як це має місце тут). Це велика відмінність від семантики інших методів jQuery, тому конкретно покладатися на це справедливо не рекомендується.

    Оновлення: Як зазначає коментар Esailija, з інженерної точки зору readyнасправді має бути статичним методом саме тому, що він працює так.

Оновлення №2: Викопуючи джерело, здається, що в якийсь момент у гілці 1.4 $()було змінено на відповідність $([]), тоді як у 1.3 це поводилося як $(document). Ця зміна посилить вищезазначені обґрунтування.


Хоча я ніколи не бачив подібного коду, стара ідіома була$(document).ready( function(){ //your code here } );
Esailija

Я не зміг зрозуміти друге оновлення, чи можете Ви ще трохи розробити? Я шукав старіші версії, але не міг знайти жодної різниці для цієї порожньої проблеми з об’єктом jQuery.
gdoron підтримує Моніку

@gdoron: Я маю на увазі зміну з selector = selector || documentна if(!selector) return this.
Джон

4

Я б сказав, що це просто той факт, що $()повертає порожній об'єкт, тоді як $(document)це не так, якщо ви застосовуєте ready()різні речі; це все ще працює, але я б сказав, що це не інтуїтивно.

$(document).ready(function(){}).prop("title") // the title
$().ready(function(){}).prop("title")  //null - no backing document

1
Так, у цій відповіді є однакові уявлення . Тож зміни відбулись у версії 1.4, яка випустила нову політику повернення.
VisioN

Я ніколи не бачив, щоб хтось міняв заголовок документа під час приєднання готового зворотного виклику, і ви можете просто зробити це за допомогою vanilla js без jQuery . Я не кажу, що це може бути не відповіддю, але це не вагома причина.
gdoron підтримує Моніку

Ну жодні властивості або методи документа не можуть бути пов'язані через$()
Alex K.

2
@AlexK. його суть полягала в тому, що насправді ніхто насправді не ланцюжить, .readyтому що це добре встановлена ​​ідіома. Звичайно, є теоретичний шанс хтось зробити це, але я ніколи не бачив, щоб код робив це (що не є вагомим аргументом, але ви знаєте: D).
Esailija

2
Можливо, через цей теоретичний випадковий метод не рекомендується , оскільки він має різну поведінку в різних випусках.
VisioN

3

Швидше за все, це лише помилка документації, яку слід виправити, єдиним недоліком використання $().ready(handler)є її читабельність. Звичайно, стверджуйте, що $(handler)це так само нечитабельно. Я згоден, тому я цим не користуюся .

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

Зрештою, це зводиться до особистих переваг. Немає мінусів у використанні $().ready(handler)крім аргументу читабельності. Я вважаю, що документація в цьому випадку є невідповідною.


+1! Ви були абсолютно праві! Вам сподобається прочитати офіційну відповідь jQuery. Я додав це як відповідь.
gdoron підтримує Моніку

2

Тільки для того, щоб зробити очевидно очевидним, що є три невідповідності у трьох, плюс я додав четверту часто використовувану форму: (function($) {}(jQuery));

За допомогою цієї розмітки:

<div >one</div>
<div>two</div>
<div id='t'/>

і цей код:

var howmanyEmpty = $().ready().find('*').length;
var howmanyHandler = $(function() {}).find('*').length;
var howmanyDoc = $(document).ready().find('*').length;
var howmanyPassed = (function($) { return $('*').length; }(jQuery));
var howmanyYuck = (function($) {}(jQuery));
var howmanyYuckType = (typeof howmanyYuck);

$(document).ready(function() {
    $('#t').text(howmanyEmpty + ":" + howmanyHandler + ":" 
        + howmanyDoc + ":" + howmanyPassed + ":" + howmanyYuckType);
});

Відображені результати div з останнього твердження: 0: 9: 9: 9: undefined

ТАК, лише версії Handler та Doc узгоджуються з конвенцією jQuery про повернення чогось із корисного, оскільки вони отримують селектор документів, а з переданою формою ви повинні щось повернути (я б не зробив цього, я б подумав, але вклав це просто щоб показати "всередині" він щось має).

Ось скрипкова версія цього для цікавих: http://jsfiddle.net/az85G/


Я не можу зрозуміти, в чому проблема, що він нічого не знаходить, контекст, який ви вказали для jQuery, nullтак .find('*').lengthповертає 0 . Ви знаходите щось погане з цією (очевидною) поведінкою?
gdoron підтримує Моніку

@gdoron - Я не знаходжу нічого поганого в цій поведінці, я просто хотів вказати на різницю порівняно з тим, коли в ньому є селектор, який НЕ є нульовим - зауважте, що цей порожній селектор, швидше за все, зазначає "швидші" коментарі в іншому місці, оскільки він має менший об’єкт для обробки, але повертає об’єкт, а не «невизначений» у цьому випадку. Мені справді це питання дуже подобається, і я його підтримав :)
Марк Шультхайс,

Причина в тому, що це швидше, тому що перша умова "розриву" ctor - це if(!selector) return thisякщо ви даєте щось інше, там відбуваються regexінші речі ... Дякую за ласкаві слова ... Я думаю, що я можу попросити команду jQuery відповісти на це (пекло, це не моя бібліотека :-)).
gdoron підтримує Моніку

Так, я не вивчав цю конкретну частину кодової бази, я зламав ядро, щоб ввести проміжні виправлення помилок, але не ту його частину. В даний час я волію бачити jQuery(document).ready(function(){});форму в нашій базі коду, оскільки існують різні рівні досвіду jQuery, і для нових людей "найбільш очевидно", що це функція обробника подій для jQuery.
Марк Шультхайс,

0

Я думаю, що це справді більше для читабельності, ніж будь-що інше.

Цей не такий виразний

$().ready(handler);

як

$(document).ready(handler)

Можливо, вони намагаються просувати якусь форму ідіоматичного jQuery.


3
$(document).ready(handler)читабельніше, ніж $(handler)рекомендується ІС ...
gdoron підтримує Моніку
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.