• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Jak zapisać 'this' podczas tworzenia obiektu bez konstruktora?

Object Storage Arubacloud
0 głosów
231 wizyt
pytanie zadane 19 sierpnia 2015 w JavaScript przez ScriptyChris Mędrzec (190,190 p.)
edycja 19 sierpnia 2015 przez ScriptyChris

Mam w kodzie zmienne globalne, m.in var exitStatus = 0; Chciałem, aby każdy podobiekt (np. checkAccountStatus) zmieniał wartość tej zmiennej z 0 na 1.

var exitStatus = 0;    // zmienna globalna

var accountMenu = function()
{
    exitStatus = 0;      //  zmienna lokalna
};

var subMenus = {
        checkAccountStatus: {   // podobiekt
              exitStatus: 1    // Nie mogę tu zapisać this.exitStatus: 1,
                               // bo WeBstorm podkreśla jako błąd składni
        }
};

Problem pojawił się po tym, gdy zauważyłem, że gdy w podobiektach wpiszę exitStatus = 1; to jest ona traktowana jako zmienna lokalna (nawet WebStorm inaczej ją koloruje) i w konsoli widzę, że wartość exitStatus jest 0 (czyli się nie zmieniła względem globalnej), natomiast wartość this.exitStatus (dla podobiektu checkAccountStatus) w konsoli widoczna jest jako 'undefined'. W sumie logiczne, bo skoro w podobiekcie utworzyłem zmienną lokalną exitStatus = 1 (a WebStorm mi to potwierdził kolorem), wobec tego nie zmienia ona wartości zmiennej globalnej (która wciąż ma 0).

Próbowałem więc w podobiekcie wpisać this.exitStatus = 1 (żeby odnosiła się do globalnego kontekstu, czyli zmiennej globalnej), no i zorientowałęm się, że w "Object Literal Notation" (nie wiem jak to dosłownie przetłumaczyć, ale jest to jeden z dwóch sposobów tworzenia obiektów), nie mogę przypisywać this. do zmiennych, jak to ma miejsce podczas tworzenia obiektów za pomocą konstruktorów, np. 

function checkAccountStatus(exitStatus){
 this.exitStatus = exitStatus;
};

Zapisałem wobec tego w ten sposób:

var subMenus = {
       checkAccountStatus: {
            show: function(){
                 exitStatus = 1;
            }
       }
};

Oczywiście, aby dokopać się do funkcji show(), muszę ją wywołać poprzez subMenus.showAccountStatus.show();, ale chodzi mi o dwie rzeczy.

1. Dlaczego w zapisie "notacyjnym" nie mogę dopisać this. do zmiennej, tylko muszę stworzyć funkcję, w której dopiero mogę tak zapisać?

2. Dlaczego exitStatus = 1 wewnątrz podobiektu checkAccountStatus jest traktowany jako zmienna lokalna, a wewnątrz funkcji tego podobiektu już jako zmienna globalna? Natomiast, gdy w funkcji tego podobiektu zapiszę this.exitStatus = 1 to wtedy zmienna ta odnosi się do podobiektu i jest znowu lokalna?

1 odpowiedź

+3 głosów
odpowiedź 19 sierpnia 2015 przez Comandeer Guru (601,110 p.)
wybrane 19 sierpnia 2015 przez ScriptyChris
 
Najlepsza

Coś przekombinowałeś i to równo… Przeanalizuj ten przykład: http://jsfiddle.net/Comandeer/ob91ybxL/

  • obiekt.method jeśli korzysta z zapisu this.globalna to zmienna ta jest zapisana jako własność obiektu obiekt. Tak samo obiekt.sub.method gdyby tak robiło zapisałoby do obiekt.sub.globalna. Funkcje bezpośrednio przypisane do obiektów mają this ustawione na ten obiekt
  • jeśli w obiekt.sub.method przypisujemy coś do globalna (bez żadnego przedrostka), JS szuka deklaracji tej zmiennej w danym scope i każdym wyższym. Ostatecznie odnajduje var globalna = 0 na samej górze (a więc doszliśmy do globalnego scope, czyli window.globalna lub global.globalna w zależności od środowiska)
  • obiekt.sub2.method zrobiliśmy jeszcze inną rzecz: wywołaliśmy funkcję wewnątrz obiekt.sub2.method. Tym samym this.globalna to to samo, co window.globalna. Funkcja zadeklarowana wewnątrz metody nie trzyma już wartości this, nie jest przypisana do żadnego obiektu - a to zwyczajowo oznacza, że w takim wypadku this === window. Takie zachowanie zostało zmienione w ES5 strict mode i ES6 - wówczas wywołanie this w funkcji, która nie jest metodą (lub nie została przypisana do żadnego obiektu) rzuca odpowiednim błędem TypeErrorhttp://jsfiddle.net/Comandeer/ob91ybxL/1/
  • natomiast to, że zmienne są rozwiązywane od danego scope wzwyż, do pierwszej napotkanej definicji zmiennej udawadnia IIFE, w którym odpalamy cały "program" - mamy tam deklarację zmiennej globalna, która nie nadpisuje wartości window.globalna

Natomiast zapis

var obj = {
    show: {
        cos: 1
    }
};

oznacza, że własność obj.show.cos ma wartość 1 - dlatego nie używa się tutaj this. I takie konstrukcje nazywa się "literałami obiektów".

komentarz 19 sierpnia 2015 przez Magicone Nałogowiec (45,100 p.)
wygląda jak poradnik :D
komentarz 19 sierpnia 2015 przez ScriptyChris Mędrzec (190,190 p.)
edycja 19 sierpnia 2015 przez ScriptyChris

Dzięki za wytłumaczenie zakresu działania 'this'.

Dlaczego w konstrukcji literałów obiektów (tak się odmienia?) nie można tego 'this' przypisać? W Twoim przykładzie:

var obj = {
    show: {
        cos: 1
    }
};

Wychodzi, że obj.show.cos, to zmienna lokalna. Ale, ja bym chciał wpisać this.cos żeby odnieść się do zmiennej globalnej (gdyby 'cos' było wcześniej zadeklarowane jako zmienna globalna). Wtedy, bez stworzenia metody nie mogę się odnieść.

http://jsfiddle.net/Chriss92/zcxx1L4j/1/

Chodzi mi o to, dlaczego przy literalnym zapisie, aby odnieść się do zmiennej globalnej, muszę tworzyć wewnętrzną metodę i tam modyfikować zmienną (bez this). Natomiast z użyciem konstruktora, zapis z this powoduje, że mogę zmienną globalną modyfikować w konstruktorze. Skąd tu wynika to ograniczenie przy zapisie literalnym, że nie można użyć this?

[edit]

Ten link jest poprawny http://jsfiddle.net/Chriss92/zcxx1L4j/2/

komentarz 19 sierpnia 2015 przez Comandeer Guru (601,110 p.)

Bo tworzysz obiekt  - ten zapis ma skracać tworzenie własności i metod obiektu. Po co masz się przy tworzeniu obiektów odwoływać nagle do zmiennej globalnej i ją modyfikować?

Natomiast z użyciem konstruktora, zapis z this powoduje, że mogę zmienną globalną modyfikować w konstruktorze.

Pod warunkiem, że źle użyjesz konstruktora i wywołasz go bez operatora new. Zresztą, jak już zauważyłem, ES5+ nie dopuszcza takiej możliwości

I jeszcze jedno: obj.show.cos to nie jest zmienna lokalna. Zmienna lokalna to zmienna zadeklarowana przy pomocy var w scope innym niż globalny. obj.show.cos to po prostu własność obiektu obj.show 

komentarz 19 sierpnia 2015 przez ScriptyChris Mędrzec (190,190 p.)

Po co masz się przy tworzeniu obiektów odwoływać nagle do zmiennej globalnej i ją modyfikować?

Ponieważ chciałem, aby podczas wywołwywania tego obiektu zmienna również była modyfikowana :) Na początku pliku JS mam kilka takich globalnych zmiennych i chciałem, aby poszczególne obiekty sobie te zmienne modyfikowały - tzn. gdy wywołam dany obiekt, to chcę aby on modyfikował te zmienne globalne, które chce.

Czyli reasumując, aby modyfikować zmienną globalną wewnątrz obiektu (przy zapisie literalnym), muszę stworzyć metodę i dopiero tam modyfikować?

komentarz 19 sierpnia 2015 przez Comandeer Guru (601,110 p.)
Tak. Chociaż z drugiej strony zastanowiłbym się czy aby na pewno te zmienne globalne są Ci potrzebne ;)
komentarz 19 sierpnia 2015 przez ScriptyChris Mędrzec (190,190 p.)
Myślę, że potrzebne do "zarządzania" programem, który piszę i z którym mam problemy :)
komentarz 19 sierpnia 2015 przez Comandeer Guru (601,110 p.)
Zawsze można całość opakować w IIFE lub moduł i nic nie wycieknie do globalnej przestrzenii ;)
komentarz 19 sierpnia 2015 przez ScriptyChris Mędrzec (190,190 p.)

Podobne pytania

0 głosów
1 odpowiedź 179 wizyt
pytanie zadane 14 sierpnia 2015 w JavaScript przez jegor377 Stary wyjadacz (13,230 p.)
0 głosów
0 odpowiedzi 495 wizyt
0 głosów
1 odpowiedź 379 wizyt
pytanie zadane 2 stycznia 2021 w JavaScript przez Oskar Szkurłat Bywalec (2,780 p.)

92,572 zapytań

141,423 odpowiedzi

319,645 komentarzy

61,959 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...