Chciałbym zrozumieć składnię wtyczki jQuery

89

Witryna jQuery zawiera podstawową składnię wtyczki dla jQuery w następujący sposób:

(function( $ ){    
  $.fn.myPlugin = function() {      
    // there's no need to do $(this) because
    // "this" is already a jquery object

    // $(this) would be the same as $($('#element'));

    this.fadeIn('normal', function(){    
      // the this keyword is a DOM element    
    });    
  };
})( jQuery );

Chciałbym tylko zrozumieć, co się tam dzieje z punktu widzenia Javascript, ponieważ nie wygląda to na składnię, którą widziałem wcześniej w JS. Oto moja lista pytań:

  1. Jeśli zamienisz funkcję ($) ... na zmienną, powiedz „the_function”, składnia wygląda następująco:

     (the_function)( jQuery );
    

    Co to jest "(jQuery);" robić? Czy nawiasy wokół the_function są naprawdę potrzebne? Dlaczego oni tam są? Czy możesz podać inny podobny fragment kodu?

  2. Zaczyna się od funkcji ($). Czyli tworzy funkcję, która, o ile wiem, nigdy nie zostanie uruchomiona, z parametrem $, który jest już zdefiniowany? Co się tam dzieje?

Dzięki za pomoc!

Ethan
źródło

Odpowiedzi:

130
function(x){ 
    x...
}

jest po prostu funkcją bez nazwy, która pobiera jeden argument „x” i robi rzeczy z x.

Zamiast „x”, które jest wspólną nazwą zmiennej, można użyć $, która jest mniej popularną nazwą zmiennej, ale nadal jest legalna.

function($){ 
    $...
}

Umieszczę go w nawiasach, aby upewnić się, że zostanie przeanalizowany jako wyrażenie:

(function($){
    $....
})

Aby wywołać funkcję, należy umieścić po niej () z listą argumentów. Na przykład, gdybyśmy chcieli wywołać tę funkcję, przekazując 3 jako wartość $, zrobilibyśmy to:

(function($){
    $...
})(3);

Tylko dla kopnięć, wywołajmy tę funkcję i przekażmy w jQuery jako zmienną:

(function($){
     $....
})(jQuery);

Tworzy to nową funkcję, która przyjmuje jeden argument, a następnie wywołuje tę funkcję, przekazując jQuery jako wartość.

CZEMU?

  • Ponieważ pisanie jQuery za każdym razem, gdy chcesz coś zrobić z jQuery, jest żmudne.

DLACZEGO NIE TYLKO PISAĆ $ = jQuery?

  • Ponieważ ktoś inny mógł zdefiniować znak $ jako coś innego. Gwarantuje to, że wszelkie inne znaczenia znaku $ są zasłonięte przez to.
Joel Spolsky
źródło
20
To jasne, ale brakuje w nim wyjaśnienia na temat potrzeby poprowadzenia parsera do przeanalizowania definicji funkcji jako wyrażenia, a nie instrukcji . Do tego służą dodatkowe nawiasy.
Pointy
16
(function(){})()jest znany jako IIFE (natychmiastowo wywoływane wyrażenie funkcyjne) . Niech będzie wiadomo, że można użyć innych symboli, aby wymusić parser traktować jako wyraz funkcji takich jak +,!,-,~(i innych) jak poniżej: !function($){}(jQuery). A dla jeszcze większej zabawy możesz ~~+-!function($){}(jQuery):!
David Murdoch,
(funkcja ($, win, doc) {$ ....}) (jQuery, okno, dokument); To też dodałbym ... Pomogło mi to lepiej zrozumieć. w tym spokoju kodu jQuery ---> $; i okno ---> win; następnie dokument ---> doc ... :) dzięki ...
Haranadh
Napotkałem przykład kodu, którego IMHO nie znajduje się na powyższej liście: $ (function () {.....} (jQuery)); (Zaczerpnięte stąd: docs.microsoft.com/en-us/aspnet/core/mvc/models/ ... ). Tutaj nie rozumiem użycia znaku $. Wydaje się, że nie jest to selektor jQuery $ (...) ani krótka składnia zdarzenia „document ready”, ponieważ funkcja nic nie zwraca. I również nie wydaje się być przedrostkiem do traktowania funkcji jako wyrażenia, ponieważ znajduje się poza nawiasami klamrowymi. Co więcej, wywołanie funkcji odbywa się WEWNĄTRZ nawiasów, więc wywołujemy deklarację.
sich
35

(function( $ ){

})( jQuery );

To jest samowykonująca się anonimowa funkcja, która używa $argumentu, dzięki czemu można jej używać ( $) zamiast jQuerywewnątrz tej funkcji i bez obawy o konflikt z innymi bibliotekami, ponieważ w innych bibliotekach również $ma specjalne znaczenie. Ten wzorzec jest szczególnie przydatny podczas pisania wtyczek jQuery.

Zamiast też możesz napisać tam dowolną postać $:

(function(j){
  // can do something like 
  j.fn.function_name = function(x){};

})(jQuery);

Tutaj jautomatycznie dogoni jQuery określone na końcu (jQuery). Lub możesz całkowicie pominąć argument, ale wtedy będziesz musiał używać jQuerysłowa kluczowego dookoła zamiast $bez obawy o kolizję. Więc $jest opakowany w argument krótkiej ręki, abyś mógł pisać $zamiast jQuerydookoła tej funkcji.

Jeśli nawet spojrzysz na kod źródłowy jQuery, zobaczysz, że wszystko jest opakowane pomiędzy:

(function( window, undefined ) {
  // jQuery code
})(window);

Jest to, jak widać, samowykonująca się anonimowa funkcja z argumentami. window(I undefined) argumentem jest stworzony i jest odwzorowany z globalnego windowobiektu na dole (window). Jest to popularny wzorzec w dzisiejszych czasach i ma niewielki wzrost szybkości, ponieważ tutaj windowbędzie analizowany z argumentu, a nie z windowobiektu globalnego, który jest zmapowany poniżej.


Jest $.fnto obiekt jQuery, w którym tworzysz nową funkcję (która jest również obiektem) lub samą wtyczkę, dzięki czemu jQuery otacza twoją wtyczkę w swoim $.fnobiekcie i udostępnia ją.


Co ciekawe, na podobne pytanie odpowiedziałem tutaj:

Składnia funkcji zamknięcia JavaScript / jQuery

Możesz również zapoznać się z tym artykułem, aby dowiedzieć się więcej o samowykonujących się funkcjach, które napisałem:

Samowykonujące się funkcje JavaScript

Sarfraz
źródło
Więc gdybym miał obiekt o nazwie my_object i zrobił to: (function (mo) {mo.doSomething ()}) (my_object), to uruchomiłoby to my_object.doSomething ()?
Ethan
3

Podstawowa składnia wtyczki umożliwia korzystanie $z odwołań jQueryw treści wtyczki, niezależnie od identyfikatora $w momencie ładowania wtyczki. Zapobiega to konfliktom nazw z innymi bibliotekami, w szczególności Prototype.

Składnia definiuje funkcję, która akceptuje parametr znany jako, $dzięki czemu można się do niego odwoływać tak, jak $w treści funkcji, a następnie natychmiast wywołuje tę funkcję, wstawiając ją jQueryjako argument.

Pomaga to również nie zanieczyszczać globalnej przestrzeni nazw (więc zadeklarowanie var myvar = 123;w treści wtyczki nie zostanie nagle zdefiniowane window.myvar), ale głównym pozornym celem jest umożliwienie używania miejsca, w $którym $mogło zostać przedefiniowane.

Steven
źródło
3

Masz tam do czynienia z samo-wywołującą się anonimową funkcją. To jak „najlepsza praktyka”, aby zawinąć wtyczkę jQuery w taką funkcję, aby upewnić się, że $znak jest powiązany z jQueryobiektem.

Przykład:

(function(foo) {
    alert(foo);
}('BAR'));

To ostrzegałoby BARpo umieszczeniu w <script>bloku. Parametr BARjest przekazywany do funkcji, która wywołuje samą siebie.

Ta sama zasada dzieje się w Twoim kodzie, jQueryobiekt jest przekazywany do funkcji, więc $na pewno będziemy odwoływać się do obiektu jQuery.

jAndy
źródło
1
Rozumiem to wszystko. Chcę wiedzieć, dlaczego / jak działa składnia nawiasów, aby utworzyć samowykonującą się funkcję? Czy to tylko cecha języka? Jak to działa?
ciało
2

Na końcu jQuery przekazuje się (jQuery) do funkcji, dzięki czemu możesz użyć symbolu $ w swojej wtyczce. Ty też mógłbyś to zrobić

(function(foo){

  foo.fn.myPlugin = function() {


    this.fadeIn('normal', function(){


    });

  };
})( jQuery );
harfa
źródło
2

Aby znaleźć jasne wyjaśnienie tej i innych nowoczesnych sztuczek javascript i typowych praktyk, polecam przeczytanie Javascript Garden.

http://bonsaiden.github.com/JavaScript-Garden/

Jest to szczególnie przydatne, ponieważ wiele z tych wzorców jest szeroko stosowanych w wielu bibliotekach, ale nie są one do końca wyjaśnione.

OlliM
źródło
2

Inne odpowiedzi tutaj są świetne, ale jest jedna ważna kwestia, która nie została omówiona. Mówisz:

Czyli tworzy funkcję, która, o ile wiem, nigdy nie zostanie uruchomiona, z parametrem $, który jest już zdefiniowany?

Nie ma gwarancji, że zmienna globalna $jest dostępna . Domyślnie jQuery tworzy dwie zmienne w zakresie globalnym: $i jQuery(gdzie dwie są aliasami tego samego obiektu). Jednak jQuery można również uruchomić w trybie noConflict :

<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript">
  jQuery.noConflict();
</script>

Kiedy wywołujesz jQuery.noConflict(), zmienna globalna $jest ustawiana z powrotem na taką, jaka była przed dołączeniem biblioteki jQuery. Dzięki temu jQuery może być używany z innymi bibliotekami Javascript, które są również używane $jako zmienna globalna.

Jeśli napisałeś wtyczkę, która opierała się na $aliasie dla jQuery, wtedy twoja wtyczka nie będzie działać dla użytkowników pracujących w trybie noConflict.

Jak już wyjaśnili inni, opublikowany kod tworzy anonimową funkcję, która jest wywoływana natychmiast. Zmienna globalna jQueryjest następnie przekazywana do tej anonimowej funkcji, która jest bezpiecznie aliasowana jako zmienna lokalna$ w funkcji.

Wyrko
źródło