Co robi wiodący średnik w bibliotekach JavaScript?


156

W kilku bibliotekach JavaScript widziałem na samym początku ten zapis:

/**
 * Library XYZ
 */
;(function () {
  // ... and so on

Chociaż czuję się doskonale ze składnią „funkcji wykonywanej natychmiast”

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

Zastanawiałem się, do czego służy wiodący średnik. Wszystko, co mogłem wymyślić, to to, że jest to ubezpieczenie. Oznacza to, że jeśli biblioteka jest osadzona w innym, błędnym kodzie, służy jako „ostatnia instrukcja kończy się tutaj najpóźniej”.

Czy ma jakieś inne funkcje?


Odpowiedzi:


140

Umożliwia bezpieczne łączenie kilku plików JavaScript w jeden, aby obsługiwać je szybciej jako jedno żądanie HTTP.


16
Ale nie byłoby to konieczne, gdyby wszystkie pliki zostały poprawnie zakodowane, prawda?
Boldewyn

8
Nie: w twoim przykładzie dostaniesz (function(){...})()(function(){...})().
Aaron Digulla

8
Chodziło mi o to, że „zakodowano poprawnie”, że każda biblioteka kończy się poprawną liczbą końcowych średników ...
Boldewyn

6
Tak, Boldewyn, ale tak nie jest.
Mathias Bynens,

13
Dwa źle zakodowane pliki nie będą pasować tylko przez fakt, że trzeci plik zawiera tę brudną poprawkę. Dlaczego konkatenator nie może dodać dodatkowych średników między plikami w wyniku?
Dávid Horváth

30

Właściwie najlepsza odpowiedź została udzielona w pytaniu, więc dla jasności zapiszę to tutaj:

Początek ;przed natychmiastowo wywołanymi wyrażeniami funkcyjnymi ma na celu zapobieganie błędom podczas dołączania pliku podczas konkatenacji do pliku zawierającego wyrażenie, które nie zostało poprawnie zakończone rozszerzeniem ;.

Najlepszą praktyką jest kończenie wyrażeń średnikami, ale jako zabezpieczenie należy również użyć wiodącego średnika.


Po co również kończyć wyrażenia średnikami, jeśli używasz obronnych średników? Albo możesz polegać na średnikach znajdujących się na końcu każdej linii, albo używasz obronnych średników. Wykonanie obu sprawia, że ​​ludzie błędnie dochodzą do wniosku, że istnieje powód, aby robić jedno i drugie. Porada dotycząca używania obronnych średników jest dobra; rada również zastąpić każde wystąpienie "\n"ze ";\n"nie ma sensu.
Vladimir Kornea

4
@VladimirKornea: ponieważ nie zawsze korzystasz tylko z własnych bibliotek :)
jvenema

@jvenema Nie wiem, dlaczego myślisz, że to robi różnicę.
Vladimir Kornea

6
Ponieważ nie możesz polegać na czyimś kodzie zgodnym z twoimi konwencjami. Koduj defensywnie, a wtedy nie musisz.
jvenema

1
@VladimirKornea Możesz to również potraktować jako defensywne, jeśli chcesz - chroni przed czyimś kodem, który nie zawsze zaczyna się od defensywnych średników.
Nathan Hinchey

26

Ogólnie rzecz biorąc, jeśli zdanie zaczyna się od (, [, /, + lub -, jest szansa, że ​​mogłoby zostać zinterpretowane jako kontynuacja wcześniejszego stwierdzenia. Zdania zaczynające się od /, + i - są w praktyce dość rzadkie) , ale instrukcje zaczynające się od (i [nie są wcale rzadkie, przynajmniej w niektórych stylach programowania JavaScript. Niektórzy programiści lubią umieszczać ochronny średnik na początku każdego takiego oświadczenia, aby działało ono poprawnie, nawet jeśli instrukcja zanim zostanie zmodyfikowany i usunięty wcześniej kończący średnik:

var x = 0 // Semicolon omitted here
;[x,x+1,x+2].forEach(console.log) // Defensive ; keeps this statement separate

Źródło:

JavaScript: The Definitive Guide, 6. wydanie


9

Nazywa się to początkowym średnikiem.

Jego głównym celem jest ochrona przed poprzedzającym kodem, który został nieprawidłowo zamknięty, co może powodować problemy. Zapobiegnie temu średnik. Jeśli poprzedni kod został nieprawidłowo zamknięty, nasz średnik to poprawi. Jeśli był poprawnie zamknięty, nasz średnik będzie nieszkodliwy i nie będzie żadnych skutków ubocznych.


7

Jednowierszową odpowiedzią jest bezpieczne połączenie wielu plików JavaScript. Używanie średnika nie powoduje problemu.

Załóżmy, że masz wiele funkcji:

IIFE 1

(function(){
  // The rest of the code
})(); // Note it is an IIFE

IIFE 2

(function(){
   // The rest of the code
})(); // Note it is also an IIFE

Na konkatenacji może to wyglądać następująco:

(function(){})()(function(){})()

Ale jeśli dodasz średnik przed funkcją, będzie to wyglądać tak:

;(function(){})();(function(){})()

Więc dodając a ;, zwraca uwagę, czy jakiekolwiek wyrażenie nie jest poprawnie zakończone.

Przykład 2

Załóżmy, że masz plik JavaScript ze zmienną:

var someVar = "myVar"

Kolejny plik JavaScript z pewną funkcją:

(function(){})()

Teraz po konkatenacji będzie to wyglądać

var someVar = "myVar"(function(){})() // It may give rise to an error

Z średnikiem będzie wyglądać następująco:

var someVar = "myVar";(function(){})()

4

Dobrze jest, gdy minimalizujesz kod JavaScript. Zapobiega nieoczekiwanym błędom składniowym.


Jak co? Czy średnik ma jakiekolwiek znaczenie dla następującego kodu, czy tylko dla hipotetycznego błędnego kodu scalonego przed rzeczywistą biblioteką?
Boldewyn

W samym tylko kodzie, bez specjalnego znaczenia, ale kiedy ten kod znajduje się w środku innych kodów i kiedy zminimalizujesz go do jednej linii, mogą wystąpić nieoczekiwane błędy, takie jak (1) brak średnika w poprzednich wierszach, (1 ) poprzedni jest również funkcjami, więc będzie () () () (), gdy pojawi się błąd, trudny do debugowania, nie możemy powiedzieć, że zawiera błędy, ponieważ przed zminimalizowaniem działa poprawnie.
TY

1
Ale z pewnością obowiązkiem minifikatora jest prawidłowe wykonanie tego. Czy minifierki buggy są obecnie normą?
Vladimir Kornea
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.