2015-05-16 26 views
8
var namepace = (function() { 

    var loca = 5; 

    var getLocal = function() { 
     loca += 1; 
     return loca; 
    }; 

    return { 
     glob: getLocal, 
     blog: loca, 
     frog: function() { 
      return loca; 
     } 
    }; 
})(); 

alert(namepace.glob()); 
alert(namepace.blog); 
alert(namepace.frog()); 

Moje pytanie jest dlaczego powrót funkcja alert(namepace.blog);5 zamiast 6 jak by się spodziewać?JavaScript zmienny zakres i wartość

Odpowiedz

6

Ważne jest, aby zrozumieć, że wszystkie nazwy w JavaScript są odniesieniami do innych obiektów.

Po utworzeniu obiektu z literałem obiektu nazwy po lewej stronie służą do odnoszenia obiektów już wymienionych przez nazwy po prawej stronie.

W tym przypadku, gdy robisz

blog: loca, 

mówisz blog odnieść wartości określonej przez loca, czyli 5. Później, gdy przyrost loca, staje 6, oznacza to, że odnosi się do inna wartość, ale blog nadal odnosi się do wartości 5.

Z tego powodu uzyskujesz 5.

Ale kiedy robisz

namepace.frog() 

otrzymujesz aktualną wartość określoną przez loca. Ponieważ przypisano 6 w getLocal, otrzymujesz 6.

Inkrementowanie tworzy nowy numer obiekt

Aby jeszcze bardziej oczywiste, gdy robisz

loca += 1; 

lub

loca++; 

co wewnętrznie dzieje, coś takiego

oldValue = loca 
newValue = oldValue + 1 
loca = newValue 

referencyjny z ECMAScript 5.1 Specyfikacja dla += i ++

Ponieważ numery są obiekty niezmienne (można zmienić wartość 5? Nie można, dlatego nazywa się obiekt niezmienny), nowy obiekt liczbowy jest tworzony z dodanym do niego obiektem, a nazwa loca jest tworzona w celu odnoszenia nowego obiektu.


Zmienne Przedmioty

Jeśli myślisz o modyfikowalnych obiektów,

var namepace = (function() { 

    var loca = []; 

    return { 
     glob: function() { 
      loca.push(1); 
      return loca; 
     }, 
     blog: loca, 
     frog: function() { 
      return loca; 
     } 
    }; 
})(); 

console.log(namepace.glob()); 
// [ 1 ] 
console.log(namepace.blog); 
// [ 1 ] 
console.log(namepace.frog()); 
// [ 1 ] 

Teraz zarówno blog i loca odnoszą się do tego samego obiektu tablicy. Co dzieje się w glob nazywa się mutowanie.Po prostu dodajesz jeden element do obiektu tablicy o dwóch nazwach: blog i loca. Dlatego namepace.blog drukuje również [ 1 ].

1

to problem logiczny. kiedy funkcja zajmuje trochę czasu. w tym czasie przypisana zmienna .. spójrz poniżej kodu. i spróbować

var namepace = (function() { 

    var loca = 5; 

    var getLocal = function() { 
     loca += 1; 
     return loca; 
    }; 
    console.log(loca); 

    return { 
     glob: getLocal, 
     blog: loca, 
     frog: function() { 
      return loca; 
     } 
    }; 
})(); 

alert(namepace.glob()); 
alert(namepace.blog); 
alert(namepace.frog()); 
0

Podczas przypisywania do namespace.blog, używasz przekazywany przez wartość do seter. Oznacza to, że nie ma odniesienia do loca.

Po uzyskaniu dostępu do wartości za pomocą namespace.frog używana jest oryginalna zmienna, która wykorzystuje zakresy definicji JavaScript w celu rozwiązania na loca, następną dostępną definicję w lokalnym łańcuchu zasięgu.

można przeczytać na określenie zakresu tutaj: What is the scope of variables in JavaScript?

1

Pomaga myśleć kontekście wykonania, gdy program jest uruchamiany JavaScript. JavaScript ocenia odniesienia (nie wartości bezpośrednio).

Kontekst globalny składa się ze zmiennych globalnych i obiektów. W tym przypadku jest to (w czasie interpreter JavaScript czyta instrukcje namespace):

namespace = {f} // namespace references a function 

Oznacza to nazw odwołuje funkcję. W pierwszym alarmie tworzony jest następujący kontekst wykonania dla przestrzeni nazw:

loca = 5    // loca references the value 5 
getLocal = {f}   // getLocal references a function 
return {    // return object with glob, blog and frog as properties 
    glob = { getLocal() } // references the function getLocal() 
    blog = 5    // blog references same value as loca: 5 
    frog = {f}   // references anonymous function 
} 

W rezultacie wywoływana jest funkcja glob. glob odwołuje się do funkcji o nazwie getLocal. Kontekst wykonania globu jest następujący:

loca = 6  // loca now references the value 6 
return loca // return value referenced by loca 

Następne wywołanie to blog, a ten zwraca wartość 5. Nie odnosi się do loca. Odwołuje się jedynie do wartości, jaką miał loca podczas tworzenia kontekstu wykonawczego. W tym czasie utworzono kontekst wykonawczy o wartości 5, a zatem blog odwołuje się do wartości 5. Niezależnie od tego, jak często wywoływany jest glob, blog nadal będzie odnosił się do wartości 5.

W ostatnim ostrzeżeniu żaba oświadczenia jest wywoływana. żaba odwołuje się do anonimowej funkcji, która jest teraz wykonywana. kontekst wykonania żaby jest następujący:

return loca // Go and get the value that is referenced by loca 

To w zasadzie to. Staraj się myśleć "odniesienie do wartości", gdy myślisz o wartości. To może pomóc przyzwyczaić się do tego. I spróbuj wizualizować konteksty wykonania, gdy program jest uruchamiany (jak bycie ludzkim debuggerem).