Niedawny tweet zawierał ten fragment kodu JavaScript.
Czy ktoś może wyjaśnić, co się w nim dzieje krok po kroku?
> function dis() { return this }
undefined
> five = dis.call(5)
Number {[[PrimitiveValue]]: 5}
> five.wtf = 'potato'
"potato"
> five.wtf
"potato"
> five * 5
25
> five.wtf
"potato"
> five++
5
> five.wtf
undefined
> five.wtf = 'potato?'
"potato?"
> five.wtf
undefined
> five
6
W szczególności nie jest dla mnie jasne:
- dlaczego wynikiem
dis.call(5)
jestNumber
jakaś[[PrimitiveValue]]
właściwość, ale wynikifive++
ifive * 5
wydają się być zwykłymi liczbami5
i25
(nieNumber
s) - dlaczego
five.wtf
właściwość znika pofive++
zwiększeniu - dlaczego
five.wtf
właściwość nie jest już nawet możliwa do ustawienia pofive++
inkrementie, mimo żefive.wtf = 'potato?'
przypisanie najwyraźniej ustawia wartość.
javascript
Nathan Long
źródło
źródło
++
Pre
aPost
przyrost? Po pomnożeniu, znowu jest toNumber
obiekt, który nie mawtf
właściwości ... Ale wciąż jest iobject
dlatego może miećproperties
..dis
zdis.call(5)
tego owija numer prymitywnego5
do obiektu typuNumber
, który zawiera5
, tak, że ten obiekt może być zwrócony jakothis
obiekt. W++
konwertuje go z powrotem do pierwotnej liczby, które nie mogą zawierać właściwości, więcwtf
zaczyna być niezdefiniowana.Odpowiedzi:
OP tutaj. Zabawnie jest to zobaczyć w przepełnieniu stosu :)
Przed przejściem przez zachowanie ważne jest wyjaśnienie kilku rzeczy:
Wartość liczbowa i obiekt
a = 3
liczbowy ( vsa = new Number(3)
) są bardzo różne. Jeden jest prymitywny, drugi jest przedmiotem. Nie możesz przypisywać atrybutów do prymitywów, ale możesz do obiektów.Przymus między nimi jest niejawny.
Na przykład:
Każde wyrażenie ma wartość zwracaną. Gdy REPL odczytuje i wykonuje wyrażenie, wyświetla się to. Zwracane wartości często nie oznaczają tego, co myślisz, i sugerują rzeczy, które po prostu nie są prawdą.
Ok, zaczynamy.
Przysięga.
Zdefiniuj funkcję
dis
i wywołaj ją za pomocą5
. Spowoduje to wykonanie funkcji5
jako jako kontekst (this
). Tutaj jest on wymuszany z wartości Number na obiekt Number. Bardzo ważne jest, aby pamiętać, że gdybyśmy byli w trybie ścisłym, tak by się nie stało .Teraz ustawiamy atrybut
five.wtf
na'potato'
, a mając pięć jako obiekt, na pewno akceptuje proste przypisanie .Ze
five
jako przedmiot, to zapewnić to może jeszcze wykonywać proste operacje arytmetyczne. To może. Czy jego atrybuty nadal się utrzymują? Tak.Zakręt.
Teraz sprawdzamy
five++
. Sztuczka z przyrostem postfiksowym polega na tym, że całe wyrażenie będzie oceniać względem oryginalnej wartości, a następnie zwiększać wartość. Wygląda nafive
to, że wciąż jest pięć, ale tak naprawdę wyrażenie zostało ocenione na pięć, a następnie ustawionefive
na6
.Nie tylko został
five
ustawiony na6
, ale został zmuszony z powrotem do wartości liczbowej i wszystkie atrybuty zostały utracone. Ponieważ prymitywy nie mogą przechowywać atrybutów,five.wtf
jest niezdefiniowane.Ponownie próbuję ponownie przypisać atrybut
wtf
dofive
. Zwracana wartość sugeruje, że się trzyma, ale w rzeczywistości tak niefive
jest, ponieważ jest wartością liczbową, a nie obiektem liczbowym. Wyrażenie ocenia na'potato?'
, ale kiedy sprawdzimy, widzimy, że nie zostało przypisane.Prestiż.
Od czasu przyrostu postfiksa
five
jest6
.źródło
int
iInteger
na przykład. Zakładam, że jest tak, abyś mógł stworzyć funkcjędoSomething(Object)
i nadal być w stanie nadać jej prymityw. W tym przypadku prymitywy zostaną przekonwertowane na odpowiadające im klasy. Ale JS tak naprawdę nie dba o typy, więc powodem jest prawdopodobnie coś innego++
jest zastosowanie ToNumber do wartości . Porównaj podobny przypadek z ciągami: jeśli maszx="5"
, tox++
zwraca liczbę5
.dis.call(5)
, przymus sprzeciwu, nigdy bym się tego nie spodziewał.Istnieją dwa różne sposoby przedstawienia liczby:
Pierwszy to prymitywny, drugi obiekt. Pod każdym względem oba cele zachowują się tak samo, z wyjątkiem tego, że wyglądają inaczej po wydrukowaniu na konsoli. Jedną ważną różnicą jest to, że jako obiekt
new Number(5)
akceptuje nowe właściwości tak jak każda zwykła{}
, podczas gdy prymityw5
nie:Jeśli chodzi o
dis.call(5)
część początkową , zobacz Jak działa słowo kluczowe „to”? . Powiedzmy, że jako argumentcall
użyto pierwszego argumentuthis
i że ta operacja zmusza liczbę do bardziej złożonejNumber
postaci obiektu. * Później++
wymusza powrót do pierwotnej postaci, ponieważ operacja dodawania+
powoduje powstanie nowej prymitywy.Number
Przedmiotem przyjmuje nowe właściwości.++
skutkuje nową prymitywną6
wartością ...... który nie ma i nie akceptuje niestandardowych atrybutów.
* Należy zauważyć, że w trybie ścisłym
this
argumentu będzie traktowana inaczej i że nie można przekształcić wNumber
. Zobacz http://es5.github.io/#x10.4.3, aby uzyskać szczegółowe informacje dotyczące implementacji.źródło
#define true false
. Lub w Javie, gdzie możesz po prostu przedefiniować, co oznaczają liczby. To są dobre, solidne języki. W rzeczywistości każdy język ma podobne „sztuczki”, w których uzyskuje się wynik, który działa zgodnie z przeznaczeniem, ale może wyglądać dziwnie.W świecie JavaScript istnieje przymus - kryminał
Nathan, nie masz pojęcia, co odkryłeś.
Badam to od tygodni. Wszystko zaczęło się w burzową noc w październiku ubiegłego roku. Przypadkowo natknąłem się na
Number
klasę - to znaczy, dlaczego na świecie JavaScript maNumber
klasę?Nie byłem przygotowany na to, co zamierzam się potem dowiedzieć.
Okazuje się, że JavaScript, nie mówiąc ci, zmienia twoje liczby na obiekty, a twoje obiekty na liczby tuż pod twoim nosem.
JavaScript miał nadzieję, że nikt go nie złapie, ale ludzie zgłaszali dziwne, nieoczekiwane zachowanie, a teraz dzięki tobie i twojemu pytaniu mam dowody, że potrzebuję szeroko rozwiać tę sprawę.
Właśnie tego się dowiedzieliśmy. Nie wiem, czy powinienem ci to mówić - możesz wyłączyć JavaScript.
Kiedy stworzyłeś tę funkcję, prawdopodobnie nie miałeś pojęcia, co będzie dalej. Wszystko wyglądało dobrze i wszystko było w porządku - na razie.
Brak komunikatów o błędach, tylko słowo „niezdefiniowane” w danych wyjściowych konsoli, dokładnie tego, czego można oczekiwać. W końcu była to deklaracja funkcji - nie powinna niczego zwracać.
Ale to był dopiero początek. Co stało się potem, nikt nie mógł przewidzieć.
Tak, wiem, spodziewałeś się
5
, ale nie to masz, czy to - masz coś innego - coś innego.To samo przytrafiło mi się.
Nie wiedziałam, co z tym zrobić. Doprowadzało mnie to do szału. Nie mogłem spać, nie mogłem jeść, próbowałem go wypić, ale żadna ilość Mountain Dew nie sprawi, że zapomnę. To po prostu nie miało sensu!
Właśnie wtedy dowiedziałem się, co tak naprawdę się dzieje - był to przymus i działo się to na moich oczach, ale byłem zbyt ślepy, aby to zobaczyć.
Mozilla próbowała go zakopać, umieszczając go tam, gdzie, jak wiedzieli, nikt by nie spojrzał - ich dokumentację .
Po godzinach rekurencyjnego czytania i ponownego czytania oraz ponownego czytania znalazłem to:
Było to jasne, jak można napisać czcionką Open Sans. To była
call()
funkcja - jak mogłam być tak głupia ?!Mój numer wcale nie był już liczbą. W momencie, w którym to przekazałem
call()
, stało się coś innego. Stało się ... przedmiotem.Na początku nie mogłem w to uwierzyć. Jak to może być prawda? Ale nie mogłem zignorować dowodów, które gromadziły się wokół mnie. Właśnie tam, jeśli tylko spojrzysz:
wtf
miał rację. Liczby nie mogą mieć właściwości niestandardowych - wszyscy to wiemy! To pierwsza rzecz, której uczą cię w akademii.Powinniśmy byli wiedzieć, kiedy zobaczyliśmy wyjście konsoli - nie był to numer, który naszym zdaniem był. To był oszust - przedmiot, który sam się podaje jako nasza słodka niewinna liczba.
To było ...
new Number(5)
.Oczywiście! To miało doskonały sens.
call()
miał pracę do wykonania, musiał wywołać funkcję, a żeby to zrobić, musiał się zaludnićthis
, wiedział, że nie może tego zrobić liczbą - potrzebował przedmiotu i był gotów zrobić wszystko, aby go zdobyć, nawet jeśli to oznaczałoby wymuszenie naszego numeru. Kiedycall()
zobaczył numer5
, zobaczył okazję.To był idealny plan: poczekaj, aż nikt nie będzie patrzył, i zamień nasz numer na obiekt, który wygląda dokładnie tak. Otrzymujemy numer, funkcja zostaje wywołana i nikt nie byłby mądrzejszy.
To był naprawdę idealny plan, ale jak wszystkie plany, nawet te idealne, była w nim dziura i mieliśmy się w to wpaść.
Widzisz,
call()
nie rozumiałem, że nie był jedynym w mieście, który mógł zmusić liczby. To był JavaScript - przymus był wszędzie.call()
wziąłem mój numer i nie zamierzałem przestać, dopóki nie zdejmę maski z jego małego oszusta i nie wystawię go całej społeczności Stack Overflow.Ale jak? Potrzebowałem planu. Pewnie, że wygląda jak liczba, ale wiem, że nie, musi istnieć sposób, aby to udowodnić. Otóż to! To wygląda jak liczba, ale może ona działać jak jeden?
Powiedziałem,
five
że potrzebuję, aby stał się 5 razy większy - nie zapytał dlaczego i nie wyjaśniłem. Zrobiłem wtedy to, co zrobiłby każdy dobry programista: pomnożyłem. Z pewnością nie było mowy, by mógł to zrobić.Cholera! Nie tylko
five
pomnażaniewtf
było w porządku . Cholera, ten facet i jego ziemniak.Co się do cholery działo? Czy myliłem się co do tej całej sprawy? Czy to
five
naprawdę liczba? Nie, muszę coś przeoczyć, wiem o tym, muszę zapomnieć o czymś tak prostym i podstawowym, że zupełnie tego nie zauważam.To nie wyglądało dobrze, pisałem tę odpowiedź od wielu godzin i nadal nie byłem bliżej wyrażenia swojej opinii. Nie mogłem tego utrzymać, w końcu ludzie przestaliby czytać, musiałem coś wymyślić i szybko o tym pomyśleć.
Czekaj, to wszystko!
five
nie było 25, wynik był 25, 25 to zupełnie inna liczba. Oczywiście, jak mogłem zapomnieć? Liczby są niezmienne. Po pomnożeniu5 * 5
nic nie zostaje przypisane do niczego, tylko tworzysz nowy numer25
.Tak musi się tutaj dziać. Jakoś, kiedy się mnożę
five * 5
,five
musi być zmuszany do uzyskania liczby i ta liczba musi być tą, która jest używana do mnożenia. To wynik tego mnożenia drukowanego na konsoli, a nie sama wartośćfive
.five
nigdy nie zostaje mu przypisane - więc oczywiście to się nie zmienia.Więc w jaki sposób mogę
five
przypisać sobie wynik operacji. Mam to. Zanimfive
nawet zdążyłem pomyśleć, krzyknąłem „++”.Aha! Miałem go! Każdy wie,
5 + 1
to6
był to dowód, że muszę wystawiać, żefive
nie był to numer! To był oszust! Zły oszust, który nie umiał liczyć. I mógłbym to udowodnić. Oto jak działa liczba rzeczywista:Czekać? Co tu się działo? westchnienie tak mnie pochwyciło,
five
że zapomniałem, jak działają operatorzy pocztowi. Kiedy używam++
na końcufive
, mówię: zwróć bieżącą wartość, a następnie zwiększfive
. Jest to wartość przed operacją, która jest drukowana na konsoli.num
było w rzeczywistości6
i mogłem to udowodnić:Czas zobaczyć, co
five
naprawdę było:... dokładnie tak powinno być.
five
było dobre - ale byłem lepszy. Gdybyfive
nadal był przedmiotem, oznaczałby, że nadal miałby własność,wtf
a ja byłbym skłonny postawić wszystko, czego nie miał.Aha! Miałem rację. Miałem go!
five
był teraz liczbą - nie był już przedmiotem. Wiedziałem, że ten sposób pomnożenia nie uratuje go tym razem. Zobaczfive++
jest naprawdęfive = five + 1
. W przeciwieństwie do mnożenia++
operator przypisuje wartość dofive
. Mówiąc dokładniej, przypisuje mu wyniki,five + 1
których tak jak w przypadku mnożenia zwraca nową niezmienną liczbę .Wiedziałem, że go mam i po prostu upewniłem się, że nie będzie mógł się z niego wydostać. Miałem jeszcze jeden test w rękawie. Gdybym miał rację i
five
naprawdę był liczbą, to nie zadziałałoby:Tym razem nie zamierza mnie oszukać. Wiedziałem,
potato?
że zostanie wydrukowany na konsoli, ponieważ to wynik zadania. Prawdziwe pytanie brzmi: czywtf
nadal tam będzie?Tak jak podejrzewałem - nic - ponieważ liczbom nie można przypisać właściwości. Dowiedzieliśmy się, że pierwszy rok w akademii;)
Dzięki Nathan. Dzięki twojej odwadze w zadawaniu tego pytania mogę w końcu odłożyć to wszystko za siebie i przejść do nowej sprawy.
Jak ten o funkcji
toValue()
. Drogi Boże. Nieee!źródło
01
deklaruje funkcję,dis
która zwraca obiekt kontekstu. Cothis
oznacza zmiany w zależności od tego, czy używasz trybu ścisłego, czy nie. Cały przykład ma inne wyniki, jeśli funkcja została zadeklarowana jako:Jest to szczegółowo opisane w sekcji 10.4.3 specyfikacji ES5
02
jest wartością zwracaną deklaracji funkcji.undefined
powinno być tutaj oczywiste.03
zmiennafive
jest inicjalizowana wartością zwracanądis
po wywołaniu w kontekście wartości pierwotnej5
. Ponieważdis
nie jest w trybie ścisłym, linia ta jest identyczna z wywołaniemfive = Object(5)
.04
DziwnaNumber {[[PrimitiveValue]]: 5}
wartość zwracana jest reprezentacją obiektu, który otacza pierwotną wartość5
05
właściwośćfive
obiektuwtf
ma przypisaną wartość ciągu'potato'
06
jest wartością zwracaną zadania i powinna być zrozumiała.07
właściwośćfive
obiektuwtf
jest badana08
jakfive.wtf
poprzednio ustawiono'potato'
, powraca'potato'
tutaj09
five
obiekt jest mnożona przez wartość pierwotnej5
. Nie różni się to niczym od żadnego mnożonego obiektu i jest wyjaśnione w sekcji 11.5 specyfikacji ES5 . Na szczególną uwagę zasługuje sposób rzutowania obiektów na wartości liczbowe, co opisano w kilku sekcjach.9.3 ToNumber :
9.1 ToPrimitive :
8.12.8 [[DefaultValue]] :
Jest to ogólny sposób stwierdzenia, że funkcja obiektu
valueOf
zostaje wywołana, a wartość zwracana z tej funkcji jest używana w równaniu. Jeśli chcesz zmienićvalueOf
funkcję, możesz zmienić wyniki operacji:10
ponieważ funkcjafive
svalueOf
pozostała niezmieniona, zwraca opakowaną pierwotną wartość5
, abyfive * 5
oceniać, w5 * 5
którym wyniku25
11
właściwośćfive
obiektuwtf
jest oceniana ponownie, mimo że nie uległa zmianie od momentu przypisania05
.12
'potato'
13
Postfix Przyrost Operator jest wywoływanafive
, która pobiera wartość liczbową (5
omówiliśmy jak wcześniej), przechowuje wartość tak, że może zostać zwrócone, dodaje1
się do wartości (6
) przypisuje wartośćfive
i zwraca zapisana wartość (5
)14
tak jak poprzednio, zwracana wartość jest wartością przed jej zwiększeniem15
dostępna jestwtf
właściwość pierwotnej wartości (6
) przechowywanej w zmiennejfive
. Sekcja 15.7.5 specyfikacji ES5 określa to zachowanie. Liczby pobierają właściwości zNumber.prototype
.16
Number.prototype
nie mawtf
właściwości, więcundefined
jest zwracany17
five.wtf
ma przypisaną wartość'potato?'
. Przypisanie jest zdefiniowane w 11.13.1 specyfikacji ES5 . Zasadniczo przypisana wartość jest zwracana, ale nie jest przechowywana.18
'potato?'
został zwrócony przez operatora przypisania19
ponowniefive
, który ma wartość,6
jest uzyskiwany i ponownieNumber.prototype
nie mawtf
właściwości20
undefined
jak wyjaśniono powyżej21
five
jest dostępny22
6
jest zwracany jak wyjaśniono w13
źródło
To całkiem proste.
Zwraca
this
kontekst. Jeśli takcall(5)
, przekazujesz numer jako obiekt.call
Funkcja nie dostarcza argumentów, pierwszy argument podać jest kontekstthis
. Zwykle, jeśli chcesz, aby było kontekstowe, dajesz{}
takdis.call({})
, co oznacza,this
że funkcja jest pustathis
. Jednak jeśli zdasz5
, wydaje się, że zostanie przekonwertowany na obiekt. Zobacz .callWięc powrót jest
object
Gdy to zrobisz
five * 5
, JavaScript widzi obiektfive
jako typ pierwotny, więc jest równoważny z5 * 5
. Co ciekawe, zrób'5' * 5
to, nadal jest równy25
, więc JavaScript wyraźnie rzuca się pod maską. Wfive
tym wierszu nie wprowadza się żadnych zmian w typie bazowymAle kiedy to zrobisz
++
, przekształci obiekt wnumber
typ pierwotny, usuwając w ten sposób.wtf
właściwość. Ponieważ wpływasz na typ bazowyźródło
++
konwertuje i przypisuje go z powrotem.++
jest równyvariable = variable + 1
. Więc przegrywaszwtf
*
Vs++
nie mylić mnie w ogóle. Posiadanie funkcji, która nie oczekuje żadnych argumentów i zwracathis
, posiadanie tej funkcji i tak przyjmuje argument i zwraca coś, co jest, ale nie jest dokładnie argumentem - to nie ma dla mnie sensu.dis.call()
robi.this
jest po prostu wskaźnikiem do obiektu, więc typy pierwotne są domyślnie konwertowane. Dlaczego funkcja bez argumentów nie może mieć przynajmniej kontekstu? Pierwszy argumentcall
lubbind
służy do ustawienia kontekstu. Ponadto funkcje są zamknięciami, co oznacza, że mają dostęp do więcej niż tylkoarguments
Wartości pierwotne nie mogą mieć właściwości. Ale gdy próbujesz uzyskać dostęp do właściwości o wartości pierwotnej, przezroczyste przejście do tymczasowego obiektu Number.
Więc:
źródło
Funkcja deklaracji
dis
. Funkcja zwraca kontekstZadzwoń
dis
z kontekstem5
. Wartości pierwotne są umieszczane w ramkach, gdy są przekazywane jako kontekst w trybie ścisłym ( MDN ). Więcfive
teraz jest obiekt (numer w pudełku).Deklaruj
wtf
właściwośćfive
zmiennejWartość
five.wtf
five
jest zapakowany5
, więc jest to jednocześnie numer i obiekt (5 * 5 = 25). To się nie zmieniafive
.Wartość
five.wtf
Rozpakowanie
five
tutaj.five
teraz jest po prostu prymitywnynumber
. Drukuje5
, a następnie dodaje1
dofive
.five
jest liczbą pierwotną6
, nie ma w niej żadnych właściwości.prymitywy nie mogą mieć właściwości, nie można tego ustawić
nie możesz tego przeczytać, ponieważ nie zostało ustawione
five
to6
z powodu wyżej po inkrementacjiźródło
Po pierwsze wygląda na to, że jest uruchamiany przez konsolę nodejs.
1.
tworzy funkcję dis (), ale ponieważ nie została ustawiona jako a,
var
nie było żadnej wartości do zwrócenia, podobnieundefined
jak wynik, mimo żedis()
został zdefiniowany. Z bokuthis
nie został zwrócony, ponieważ funkcja nie została wykonana.2)
Powrócisz javascript na
Number
przedmiot, ponieważ po prostu ustawić funkcjędis()
„sthis
wartość prymitywnego pięciu.3)
Pierwsze powroty
"potato"
, bo po prostu ustawić właściwośćwtf
ofive
celu'potato'
. JavaScript zwraca wartość zmiennej można ustawić, dzięki czemu jest łatwy do wielu zmiennych łańcuchowych i ustawić je na taką samą wartość jak ten:a = b = c = 2
.4
Zwraca to,
25
ponieważ właśnie pomnożyłeś pierwotną liczbę5
dofive
. Wartośćfive
została określona przez wartośćNumber
obiektu.5
Wcześniej pomijałem tę linię, ponieważ chciałbym ją tutaj powtórzyć. Zwraca tylko wartość właściwości
wtf
ustawionej powyżej.6.
Jak powiedział @Callum,
++
skonwertuje typ nanumber
tę samą wartość z obiektuNumber {[[PrimitiveValue]]: 5}}
.Ponieważ
five
jest tonumber
, nie możesz już ustawiać dla niego właściwości, dopóki nie zrobisz czegoś takiego:lub
Zauważ też, że drugi sposób będzie
Number
działał inaczej niż przy użyciu pierwszej metody, ponieważ definiuje obiekt ogólny zamiast obiektu, który został wcześniej utworzony.Mam nadzieję, że to pomaga, javascript lubi zakładać różne rzeczy, więc może stać się mylący przy przechodzeniu z
Number
obiektu na prymitywnumber
. Możesz sprawdzić, co to jest za pomocątypeof
słowa kluczowego, pisząc typ pięć po zainicjowaniu zwraca'object'
i po wykonaniufive++
zwraca'number'
.@deceze bardzo dobrze opisuje różnicę między obiektem Number a liczbą pierwotną.
źródło
Zakresy JavaScript są wykonane z kontekstów wykonania. Każdy kontekst wykonania ma środowisko leksykalne (wartości o zasięgu zewnętrznym / globalnym), środowisko zmienne (wartości o zasięgu lokalnym) i to powiązanie .
Tego wiązania jest bardzo ważną częścią kontekstu wykonania. Użycie
call
jest jednym ze sposobów zmiany tego powiązania , a to spowoduje automatyczne utworzenie obiektu do wypełnienia powiązania.Function.prototype.call () (z MDN)
Gdy okaże się, że 5 jest przekształcane
new Number(5)
, reszta powinna być raczej oczywista. Zauważ, że inne przykłady również będą działać, o ile są prymitywnymi wartościami.źródło
Kilka pojęć wyjaśnia, co się dzieje
5
jest liczbą, pierwotną wartościąNumber {[[PrimitiveValue]]: 5}
jest instancją Number (nazwijmy to wrapperem obiektów)Ilekroć uzyskujesz dostęp do właściwości / metody pierwotnej wartości, silnik JS utworzy opakowanie obiektu odpowiedniego typu (
Number
for5
,String
for'str'
iBoolean
fortrue
) i rozwiąże wywołanie dostępu / metody właściwości dla tego opakowania obiektu. Tak się dzieje, kiedy to robisztrue.toString()
na przykład .Podczas wykonywania operacji na obiektach są one konwertowane na prymitywne wartości (za pomocą
toString
lubvalueOf
) w celu rozwiązania tych operacji - na przykład podczas wykonywaniastring
odbędzie się konkatenacji ciągmystr
iobj.toString()
inumber
obejmie dodawanie3
iobj.valueOf()
.Teraz wszystko razem
dis.call(5)
zachowuje się tak,(5).dis()
jakby5
rzeczywiście miał tę metodędis
. W celu rozwiązania wywołania metody tworzone jest opakowanie obiektu, a wywołanie metody jest na nim rozstrzygane. W tym momencie pięć punktów otacza obiekt wokół pierwotnej wartości 5.Ustawienie właściwości obiektu, nic szczególnego.
W rzeczywistości
five.valueOf() * 5
uzyskuje to pierwotną wartość z opakowania obiektu.five
nadal wskazuje na obiekt początkowy.To jest faktycznie
five = five.valueOf() + 1
. Przed tym wierszemfive
otacza obiekt wokół wartości 5, a po tym punkciefive
zawiera wartość pierwotną6
.five
nie jest już przedmiotem. Każda z tych linii tworzy nową instancję Number w celu rozwiązania.wtf
dostępu do właściwości. Instancje są niezależne, więc ustawienie właściwości na jednej nie będzie widoczne na drugiej. Kod jest całkowicie równoważny z tym:źródło