Rozważ następujący kod:

<script>
    var i = 0;
    function test() {
        var _this = this;
        // foo and _this.foo are set to the same number
        var foo = _this.foo = i++;

        function wtf() {
            console.log(_this.foo, foo);
        }

        $("#thediv").click(wtf);
    };
    test();
    test();
    test();
</script>

Wydaje się, że konsola.log (_tis.foo, foo) powinien zawsze wyjść równe liczby (I).

Ale klikając linie Div Divs 3 (dla każdej połączenia konsoli.log):

2 0
2 1
2 2

Wygląda na to, że _this.foo zawsze odnosi się do ostatniego this.foo. Dlaczego tak jest?

2
Evgenyt 9 grudzień 2011, 23:17

5 odpowiedzi

Najlepsza odpowiedź

Gdy test () jest uruchamiany, this jest odniesieniem do window dla każdego z trzech połączeń (), więc faktycznie aktualizujesz window.foo po przypisaniu _this.foo i odwołuje się window.foo w swoim console.log.

Następnie, gdy wywołane są wtf() zmienne _this w każdym zamknięciu wtf() są takie same - wszystkie one window

Zobacz to JSFiddle: http://jsfiddle.net/8cyhm/

Dodałem dodatkowe parametry do Console.log, aby pokazać, co się dzieje

2
George 9 grudzień 2011, 19:37

W twojej funkcji wtf wartość przechwycona w zmiennej foo jest skalarnym - rzeczywistą wartością numeryczną. Ponieważ w momencie przechwycenia wartości skalarnej, funkcja jest tworzona, funkcja ta zamyka się o wartości 0, 1, 2 itp. Dlatego wydaje się przyrostować.

Jednakże, gdy _ jest schwytany, jest przechwycony jako odniesienie do pojedynczej instancji, która ma pola o imieniu foo. Dlatego, z _tis.Foo, odnosząc się do pola w tej samej instancji.

Aby sumować, typy wartości, takie jak liczby całkowite przechwytywane według ich wartości, podczas gdy obiekt jest przechwytywany przez jego odniesienie.

3
John Gibb 9 grudzień 2011, 19:25

To trudny, :)

Pierwsza i najważniejsza rzecz, którą musisz zrozumieć, nazywasz funkcję test bez prefiksu new, co sprawia, że this wskaźnik w funkcji odnoszą się do {{x3} } Object.

<script>
    var i = 0;
    function test() {
        var _this = this; //** this referes to the window object
        var foo = _this.foo = i++; //** incrementing the global var and assigning that to a local var and a window.foo var

        function wtf() {
            console.log(_this.foo, foo); //** reads window.foo and its local var foo
        }

        $("#thediv").click(wtf); //** creates a new lister every time the test function gets called
    };
    //** calling without the new keyword
    test(); //** creates foo-1, and wft-1 in memory, assigns foo-1=0; window.foo=0
    test(); //** creates foo-2, and wft-2 in memory, assigns foo-2=1; window.foo=1
    test(); //** creates foo-3, and wft-3 in memory, assigns foo-3=2; window.foo=2
</script>

(plz przeczytaj komentowaną część wewnątrz kodu)

Teraz, gdy klikniesz na div, który praktycznie ma 3 funkcje, słuchając zdarzenia kliknięć (3 inline {x1}} funkcji w funkcji {x2}}) (każde połączenie do {{x3} } Funkcja tworzy nową funkcję inline wtf). Każda z tych funkcji inline odczytuje swój lokalny var {x5}}, który każdy ma odpowiednio wartości 1,2,3.

1
Jim Jose 9 grudzień 2011, 20:03

Tak to działa:

Funkcja test jest wywołana trzy razy. Za każdym razem, gdy obiekt funkcyjny } wtf jest tworzony i związany z div jako jego kliknięcie. Oznacza to, że po wykonaniu powyższego kodu pojawi się trzy kliknięcia związane z div. Po kliknięciu div te te trzy ręczne są wywołane w kolejności.

Ta linia

var _this = this;

Tylko przechowuje obiekt globalny do zmiennej lokalnej _this. Jeśli funkcja test miała być wywołana w ścisłym środowisku, this byłby undefined, a kod rzucił błąd. Jednak ponieważ nie jest to ścisły tryb, wartość this odnosi się do obiektu globalnego.

BTW, zmienna i jest zadeklarowana w kodzie globalnym, co czyni go zmienną globalną (własność globalna).

Ta linia

var foo = _this.foo = i++;

Przypisuje bieżącą wartość i zarówno do zmiennej lokalnej foo i do _this.foo. A ponieważ _this jest odniesieniem do globalnego obiektu, właściwość {X4}} jest właściwością globalną (tak jak i).

Teraz, ponieważ wywołaliśmy funkcję test trzy razy, istnieją również trzy oddzielne zmienne lokalne foo. Każda z tych zmiennych przechwytuje wartość zmiennej i w momencie wywołanej funkcji test. Tak więc wartości tych trzech foo zmienne są 0, 1 i 2. Zmienne te są przechwytywane przez funkcje trzech wtf (odpowiednio) poprzez zamknięcie. (Funkcja pierwsza wtf przechwytuje pierwszą zmienną {{x10}} i tak dalej.)

Jednak w przeciwieństwie do zmiennych {X0}}, jest tylko jeden foo Global. Więc po każdym wywołaniu funkcji {x2}} foo właściwość globalna jest zwiększana. W wyniku, po test został wywołany trzy razy, wartość _this.foo jest 2. (Jest to przed Div został kliknięty.)

Teraz, gdy div jest kliknięty, trzy wtf funkcje będą wykonywane. Każda z tych funkcji wydrukuje wartość _this.foo, która jest 2. Jednak każdy z tych funkcji wtf uchwycił różne foo zmienna poprzez zamknięcie. Wartości tych trzech {X5}} zmienne są 0, 1 i 2.

1
Šime Vidas 9 grudzień 2011, 20:10

Jeśli testujesz w Chrome, możesz uderzyć w błąd w konsoli.log. Zobacz: JavaScript Funky Array Mishap

Spróbuj zmienić:

console.log(_this.foo + ' = ' + foo);
-2
Community 23 maj 2017, 10:34