Słowo new
kluczowe w JavaScript może być dość mylące, gdy pojawia się po raz pierwszy, ponieważ ludzie myślą, że JavaScript nie jest zorientowanym obiektowo językiem programowania.
- Co to jest?
- Jakie problemy rozwiązuje?
- Kiedy jest to właściwe, a kiedy nie?
javascript
new-operator
Alon Gubkin
źródło
źródło
Odpowiedzi:
Robi 5 rzeczy:
this
zmienna wskazuje na nowo utworzony obiekt.this
jest wspomniane.null
odwołanie niebędące obiektem. W takim przypadku zwracane jest odwołanie do obiektu.Uwaga: funkcja konstruktora odnosi się do funkcji po
new
słowie kluczowym, jak wPo wykonaniu tej czynności, jeśli zażądana zostanie niezdefiniowana właściwość nowego obiektu, skrypt sprawdzi obiekt [[prototyp]] obiektu pod kątem właściwości. W ten sposób możesz uzyskać coś podobnego do tradycyjnego dziedziczenia klas w JavaScript.
Najtrudniejszą częścią tego jest punkt 2. Każdy obiekt (łącznie z funkcjami) ma tę wewnętrzną właściwość o nazwie [[prototyp]] . Można go ustawić tylko w czasie tworzenia obiektu, za pomocą nowego , za pomocą Object.create lub w oparciu o literał (funkcje domyślnie to Function.prototype, liczby to Number.prototype itp.). Można go odczytać tylko za pomocą Object.getPrototypeOf (someObject) . Nie ma innego sposobu na ustawienie lub odczytanie tej wartości.
Funkcje, oprócz właściwości hidden [[prototype]] , mają również właściwość o nazwie prototype , i to do niej można uzyskać dostęp i modyfikować, aby zapewnić odziedziczone właściwości i metody dla tworzonych obiektów.
Oto przykład:
To jest jak dziedziczenie klas, ponieważ teraz
new ObjMaker()
wydaje się, że wszelkie obiekty, które tworzysz, odziedziczyły właściwość „b”.Jeśli chcesz coś w rodzaju podklasy, wykonaj następujące czynności:
Przeczytałem mnóstwo śmieci na ten temat, zanim w końcu znalazłem tę stronę , na której wyjaśniono to bardzo dobrze za pomocą ładnych schematów.
źródło
ObjMaker
jest zdefiniowane jako funkcja zwracająca wartość?new
istnieje, więc nie musisz pisać metod fabrycznych do konstruowania / kopiowania funkcji / obiektów. Oznacza to: „Skopiuj to, czyniąc to tak, jak jego nadrzędna„ klasa ”; rób to skutecznie i poprawnie; i przechowuj informacje o spadku, które są dostępne tylko dla mnie, JS, wewnętrznie”. W tym celu modyfikuje niedostępne w inny sposób wnętrzeprototype
nowego obiektu, aby nieprzezroczysto hermetyzować odziedziczone elementy, naśladując klasyczne łańcuchy dziedziczenia OO (których nie można modyfikować w czasie wykonywania). Możesz to zasymulować beznew
, ale dziedziczenie będzie modyfikowalne w czasie wykonywania. Dobrze? Zły? Zależy od Ciebie.Notice that this pattern is deprecated!
. Jaki jest prawidłowy aktualny wzorzec, aby ustawić prototyp klasy?Załóżmy, że masz tę funkcję:
Jeśli wywołasz to jako samodzielną funkcję, taką jak:
Wykonanie tej funkcji doda dwie właściwości do
window
obiektu (A
iB
). Dodaje to do,window
ponieważwindow
jest to obiekt, który wywołał funkcję podczas jej wykonywania, awthis
funkcji jest obiekt, który wywołał funkcję. Przynajmniej w JavaScript.Teraz nazwij to tak
new
:Po dodaniu
new
do wywołania funkcji dzieje się, że nowy obiekt jest tworzony (tylkovar bar = new Object()
) i żethis
wewnątrz funkcji wskazuje na nowoObject
utworzony właśnie obiekt, a nie na obiekt, który wywołał funkcję. Tak więcbar
jest teraz obiektem o właściwościachA
iB
. Każda funkcja może być konstruktorem, to po prostu nie zawsze ma sens.źródło
window
niejawną. Nawet w zamknięciu, nawet jeśli anonimowy. Jednak w tym przykładzie jest to proste wywołanie metody w oknie:Foo();
=>[default context].Foo();
=>window.Foo();
. W tym wyrażeniuwindow
jest kontekst (nie tylko dzwoniący , co nie ma znaczenia).Oprócz odpowiedzi Daniela Howarda, oto, co
new
robi (a przynajmniej wydaje się, że robi):Podczas
jest równa
źródło
func.prototype
aby byćnull
? Czy mógłbyś rozwinąć tę kwestię?A.prototype = null;
W takim przypadkunew A()
powstanie obiekt, to znaczy wewnętrzny prototyp wskazuje naObject
obiekt: jsfiddle.net/Mk42ZObject(ret) === ret
.typeof
test po prostu ułatwia zrozumienie, co dzieje się za kulisami.Dla początkujących, aby lepiej to zrozumieć
wypróbuj następujący kod w konsoli przeglądarki.
Teraz możesz przeczytać odpowiedź wiki społeczności :)
źródło
return this;
daje taką samą wydajność.Służy do tego właśnie. Konstruktor funkcji definiuje się w następujący sposób:
Jednak dodatkową zaletą ECMAScript jest to, że możesz rozszerzyć tę
.prototype
właściwość, abyśmy mogli zrobić coś takiego ...Wszystkie obiekty utworzone z tego konstruktora będą teraz miały
getName
łańcuch prototypowy, do którego mają dostęp.źródło
class
słowa kluczowego, ale można zrobić prawie to samo.JavaScript jest zorientowanym obiektowo językiem programowania i jest używany dokładnie do tworzenia instancji. Jest oparty na prototypach, a nie klasach, ale to nie znaczy, że nie jest zorientowany obiektowo.
źródło
JavaScript jest dynamicznym językiem programowania, który obsługuje paradygmat programowania obiektowego i służy do tworzenia nowych instancji obiektów.
Klasy nie są konieczne dla obiektów - JavaScript jest językiem opartym na prototypach .
źródło
Istnieją już bardzo świetne odpowiedzi, ale zamieszczam nową, aby podkreślić moją obserwację w przypadku III poniżej, co dzieje się, gdy masz wyraźną instrukcję return w funkcji, którą
new
wymyślasz. Spójrz na poniższe przypadki:Przypadek I :
Powyżej jest zwykły przypadek wywołania wskazanej funkcji anonimowej
Foo
. Gdy wywołujesz tę funkcję, ona zwracaundefined
. Ponieważ nie ma wyraźnej instrukcji return, interpreter JavaScript na siłę wstawiareturn undefined;
instrukcję na końcu funkcji. Tutaj okno jest obiektem wywołania (kontekstowymthis
), który otrzymuje noweA
iB
właściwości.Przypadek II :
Tutaj interpreter JavaScript, widząc
new
słowo kluczowe, tworzy nowy obiekt, który działa jako obiekt wywołania (kontekstowythis
) wskazywanej przez anonimową funkcjęFoo
. W takim przypadkuA
iB
stają się właściwościami nowo utworzonego obiektu (zamiast obiektu okna). Ponieważ nie masz żadnej wyraźnej instrukcji return, interpreter JavaScript zdecydowanie wstawia instrukcję return, aby zwrócić nowy obiekt utworzony z powodu użycianew
słowa kluczowego.Przypadek III :
Tutaj znowu interpreter JavaScript, widząc
new
słowo kluczowe, tworzy nowy obiekt, który działa jak obiekt wywołania (kontekstowythis
) wskazanej przez anonimową funkcjęFoo
. PonownieA
iB
stań się właściwościami nowo utworzonego obiektu. Ale tym razem masz wyraźną instrukcję return, więc interpreter JavaScript nie zrobi nic własnego.W przypadku III należy zauważyć, że obiekt tworzony z powodu
new
słowa kluczowego został utracony z radaru.bar
wskazuje na zupełnie inny obiekt, który nie jest tym, który interpreter JavaScript utworzył z powodunew
słowa kluczowego.Cytując Davida Flanagana z JavaScripit: The Definitive Guide (wydanie 6), rozdz. 4, strona # 62:
--- Informacje dodatkowe ---
Funkcje używane we fragmencie kodu powyższych przypadków mają specjalne nazwy w świecie JS, jak poniżej:
Przypadek I i II - funkcja konstruktora
Przypadek III - funkcja fabryczna. Funkcje fabryczne nie powinny być używane ze
new
słowem kluczowym, które zrobiłem, aby wyjaśnić tę koncepcję w bieżącym wątku.O różnicy między nimi możesz przeczytać w tym wątku.
źródło
czasami kod jest łatwiejszy niż słowa:
dla mnie, dopóki nie prototypuję, używam stylu func2, ponieważ daje mi to nieco większą elastyczność wewnątrz i na zewnątrz funkcji.
źródło
B1 = new func2(2);
<- Dlaczego tego nie będzieB1.y
?Słowo
new
kluczowe zmienia kontekst, w którym funkcja jest uruchamiana, i zwraca wskaźnik do tego kontekstu.Kiedy nie używasz
new
słowa kluczowego, kontekstem, w którymVehicle()
działa funkcja, jest ten sam kontekst, z którego wywołujeszVehicle
funkcję. Słowothis
kluczowe będzie odnosić się do tego samego kontekstu. Gdy używasznew Vehicle()
, tworzony jest nowy kontekst, więc słowo kluczowethis
wewnątrz funkcji odnosi się do nowego kontekstu. W zamian dostajesz nowo utworzony kontekst.źródło
Słowo
new
kluczowe służy do tworzenia nowych instancji obiektów. I tak, javascript to dynamiczny język programowania, który obsługuje paradygmat programowania obiektowego. Konwencja dotycząca nazewnictwa obiektów polega na tym, aby zawsze używać wielkiej litery w przypadku obiektów, które powinny być tworzone przez nowe słowo kluczowe.źródło
Podsumowanie:
Słowo
new
kluczowe jest używane w javascript do utworzenia obiektu z funkcji konstruktora. Słowonew
kluczowe musi zostać umieszczone przed wywołaniem funkcji konstruktora i będzie wykonywać następujące czynności:this
słowo kluczowe z nowo utworzonym obiektem i wykonuje funkcję konstruktoraPrzykład:
Co dokładnie się dzieje:
const doggie
mówi: Potrzebujemy pamięci do deklarowania zmiennej.=
mówi: Zainicjujemy tę zmienną wyrażeniem po=
new Dog(12)
. Silnik JS widzi nowe słowo kluczowe, tworzy nowy obiekt i ustawia prototyp na Dog.prototypethis
wartością ustawioną na nowy obiekt. Na tym etapie jest przypisywany wiek do nowo utworzonego obiektu pieska.źródło
Słowo
new
kluczowe tworzy instancje obiektów za pomocą funkcji jako konstruktora. Na przykład:Instancje dziedziczą
prototype
po funkcji konstruktora. Biorąc pod uwagę powyższy przykład ...źródło
Cóż, JavaScript na si może znacznie różnić się w zależności od platformy, ponieważ jest to zawsze implementacja oryginalnej specyfikacji EcmaScript.
W każdym razie, niezależnie od implementacji, wszystkie implementacje JavaScript zgodne z prawą specyfikacji EcmaScript dadzą ci język zorientowany obiektowo. Zgodnie ze standardem ES:
Teraz, kiedy ustaliliśmy, że JavaScript jest implementacją EcmaScript, a zatem jest językiem obiektowym. Definicja
new
operacji w dowolnym języku obiektowym mówi, że takie słowo kluczowe służy do tworzenia instancji obiektu z klasy określonego typu (w tym typów anonimowych, w przypadkach takich jak C #).W EcmaScript nie używamy klas, jak można przeczytać w specyfikacji:
źródło