2015-06-14 22 views
5

Martwię się o to od jakiegoś czasu i nie mogę zrozumieć, co się naprawdę dzieje. Wyjaśnienie w komentarzach do kodu. Istnieją dwie wersje aplikacji, jedna z nich rzuca dziwne wyniki, a druga wykonuje oczekiwaną pracę.Bardzo dziwne zachowanie przy użyciu słowa kluczowego "var" w żądaniu ajaxowym

var id = "test1"; 

$.post("http://fiddle.jshell.net/echo/json/", {"data": "data"}, function(a) { 
    alert(id); // will throw undefined 

    var id = "test2"; 
    alert(id); // will throw "test2" as expected 
}); 

$.post("http://fiddle.jshell.net/echo/json/", {"data": "data"}, function(a) { 
    alert(id); // will throw "test1" as expected 

    id = "test2"; 
    alert(id); // will throw "test2" as expected 
}); 

Nie jestem pewien, czy to ma coś wspólnego z wywołania ajax lub anonimowej funkcji, ale jest to po prostu sposób odkryłem to, więc lepiej trzymać go tam. Czy ktoś mógłby wyjaśnić, czego mi brakuje? Dlaczego zachowuje się inaczej, gdy anuluję słowo kluczowe var? Możesz wypróbować wszystko, co trzeba: here on jsFiddle

+0

nie czuję ten jest dokładną kopią jak to pytanie zadawane w czasie I nie każdy ma pomysł podnoszenia. Jest to raczej pytanie, które pyta "co to jest", a nie "jak się zachowuje". Głosowanie na ponowne otwarcie –

Odpowiedz

8

Fajnie, odkryłeś hoisting. MDN wyjaśnia to tak dobre, jak każdy:

Ponieważ deklaracje zmiennych (i oświadczenia w ogóle) są przetwarzane przed każdy kod jest wykonywany, deklarując zmienną nigdzie w kodzie jest równoznaczne z deklarując go na górze. Oznacza to także, że zmienna może wydawać się użyta przed jej zadeklarowaniem. To zachowanie jest nazywane "podnoszeniem", ponieważ wydaje się, że deklaracja zmiennej zostanie przeniesiona na szczyt funkcji lub kod globalny.

przykładowy kod z MDN link poniżej:

bla = 2 
var bla; 
// ... 

// is implicitly understood as: 

var bla; 
bla = 2; 

Można zobaczyć, jak to będzie skutkowało w "dziwne zachowanie":

alert(testId); 
var testId = 2; 

odpowiada:

var testId; 
alert(testId); 
testId = 2; 

Co prowadzi mnie do ostatniej wiedzy, którą mogę przekazać, zawsze deklarować zmienne w górnej części bloków kodu, więc to „dziwne zachowanie” jest kodowana do swoich programów (i nigdy nie rzuca cię znowu):

function someFunction() { 
    var 
    firstVar, 
    secondVar, 
    thirdVar; 

    //rest of your code statements here 
} 

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/var#var_hoisting

+1

Wow, właśnie nauczyłem się naprawdę interesującej rzeczy! Założę się, że będę o tym pamiętać, dziękuję –

+0

Po prostu inne pytanie, czy oznacza to, że każda linia, która nie jest nigdy kiedykolwiek wykonana (wewnątrz funkcji) może złamać cały kod? W oparciu o twoją ostatnią edycję, każe mi myśleć, że robi "wciąganie" tylko przed wykonaniem funkcji. Czy mam rację? –

+0

@Martin. absolutnie.'var dziesięć = 10; (function() {if (fałsz) {var dziesięć = fałsz;} alert (dziesięć);/* alerty nieokreślone, na pierwszy rzut oka można się spodziewać alarmu 10 * /}()); ' – Adam

3

Nazywa wyciągowych. var id zostaje przeniesiony na początek funkcji.

+0

Bez wypełniania wartości? –

+1

@Martin - poprawne. Deklaruje zmienną przed jakimikolwiek innymi instrukcjami kodowymi, więc nie jest niezdefiniowana, a następnie przypisuje ją do oryginalnej linii kodu. – Adam

4

Tak jak mówili inni, jest to podnoszenie. Ale tak więc można mieć jaśniejszy obraz tego, co się dzieje, pierwszy kod jest faktycznie wykonywana tak:

var id = "test1"; 

$.post("http://fiddle.jshell.net/echo/json/", {"data": "data"}, function(a) { 
    // this is because of hoisting 
    var id = undefined; 
    alert(id); // will throw undefined 

    id = "test2"; 
    alert(id); // will throw "test2" as expected 
}); 
+1

Cóż, myślę, że nie jestem do końca pewien, dlaczego tak się dzieje. Przechodzi przez kod, inicjalizując zmienną "id" bez wypełniania jakiejkolwiek wartości (usuwając wartość z pierwszej linii) i wypełnia jej wartość do "test2" po pierwszym alarmie? –

+0

@Martin. Dokładnie tak, jak powiedziałeś. –