Ta strona używa ciasteczek (cookies), dzięki którym nasz serwis może działać lepiej. Dowiedz się więcej OK, rozumiem

operator new + self-invoking functions

Tworzenie dynamicznych stron internetowych z zastosowaniem JavaScript, jQuery, Ajax. Dowiedz się jak to zrobić, znajdź rozwiązania swoich problemów.

operator new + self-invoking functions

Post 07.09.2017, 14:32:56

Czesc,

Spotkałem niedawno konstrukcję, którą dla uproszczenia zdefiniuję jako:

Kod: Zaznacz cały
var foo = new (function(){
    this.name = "Ania"
})


Utworzy mi to nowy obiekt, aczkolwiek nie rozumiem w jaki sposób. Operatora new używa się z funkcją - ok, w sumie funkcję mamy. Ale funkcja ta wpierw się wykona i zostanie nam zwrócony undefined (co innego gdyby została nam zwrócona funkcja), zatem nie ma na czym zrobić new. Czegos nie łapię, proszę o sprostowanie.

Dziękuję,
Pozdrawiam!
whitty
Posty: 88
Dołączył(a): 12.07.2015

Re: operator new + self-invoking functions

Post 07.09.2017, 14:55:07

ok, w sumie funkcję mamy. Ale funkcja ta wpierw się wykona

w tym kodzie nie widzę wykonania funkcji, chyba, że zjadłeś jeszcze () na końcu. Na dowód, usuń z tego kodu operator new i daj na koniec console.log(foo); i zobacz co jest wartością zmiennej foo.

Ale gdyby dodać () na końcu to i tak to nic nie zmieni. Chodzi o to, że notacja ta zostanie zinterpretowana jako
Kod: Zaznacz cały
MemberExpression : new MemberExpression Arguments
(https://es5.github.io/#x11.2.2), czyli mamy operator new, po którym mamy konstruktor
Kod: Zaznacz cały
(function () { this.name = 'Ania'; })

po którym mamy argumenty (w tym wypadku pusta lista argumentów)
Kod: Zaznacz cały
()
więc interpreter będzie kontynuował zgodnie z logiką działania operatora new.

W telegraficznym skrócie, w tym kodzie mamy jedną operację – wywołanie operatora new wraz z przekazaniem mu 2 parametrów - konstruktora oraz listy argumentów i to wynika ze składni, która wyglądem mocno przypomina tradycyjne wywołanie funkcji, stąd możliwe nieporozumienie, że mamy 2 niezależne operacje - wywołanie funkcji i przekazanie jej wyniku do operatora new.

Jeśli chciałbyś wywołać funkcję i jej wynik przekazać do operatora new, to możesz nawiasy z parametrami" przesunąć do środka tych pozostałych nawiasów

Kod: Zaznacz cały
var foo = new (function(){
    this.name = "Ania"
}());

w tym wypadku powinieneś dostać błąd, że "(intermediate value)(...) is not a constructor")
Avatar użytkownikakuku
Rafał Kukawski

+∞
+∞

Posty: 19640
Dołączył(a): 14.04.2002

Re: operator new + self-invoking functions

Post 08.09.2017, 13:34:52

Dziękuję Kuku za odpowedź.

Czy zatem dobrze rozumiem, jezeli chodzi o kolejnosc tworzenia się konstruktora - w przypadku operatora new wpierw brana jest pod uwagę funkcja, a poźniej przekazywane są argumenty? Po prostu uważałem, że w przypadku funkcji samowywołującej sie, kolejnosc bedzie inna. Czyli wpierw sie funkcja wykona, a pozniej wkracza do akcji operator new.

Pozdrawiam!
whitty
Posty: 88
Dołączył(a): 12.07.2015

Re: operator new + self-invoking functions

Post 08.09.2017, 13:46:46

Po prostu uważałem, że w przypadku funkcji samowywołującej sie, kolejnosc bedzie inna.

tak jak napisałem, składnia jest myląca, bo bardzo przypomina wywołanie funkcji, po prostu traktuj new funkcja argumenty jako jedną całość, której zachowanie jest opisane w podlinkowanej części specyfikacji, zaś fragment

Kod: Zaznacz cały
(function () { })


zwraca funkcję, więc notacja operatora new jest spełniona.
Avatar użytkownikakuku
Rafał Kukawski

+∞
+∞

Posty: 19640
Dołączył(a): 14.04.2002

Re: operator new + self-invoking functions

Post 08.11.2017, 15:30:32

Czesc Kuku,

Przypomnial mi sie temat. Mam małą prośbę. Czy mógłbyś napisać krótki prosty przykład, jak by mozna wykorzystac drugi argument operatora NEW (nie moge znaleźć podobnej sytuacji)? Pierwszy argument jako konstruktor - zrozumiałe. Ale pozostałe możliwości?

Dziękuje i pozdrawiam!
whitty
Posty: 88
Dołączył(a): 12.07.2015

Re: operator new + self-invoking functions

Post 08.11.2017, 16:19:43

Co masz konkretnie na myśli?

Dajmy na to, że mamy
Kod: Zaznacz cały
var arr = new Array(1,2,3,4,5);

pierwszym argumentem jest "Array", a drugim jest lista parametrów dla Array, czyli "(1,2,3,4,5)"

Tak jak w poprzednich postach próbowałem przekazać, nie traktuj Array(1,2,3,4,5) w połączeniu z new jako jednej całości, tylko jako dwie osobne rzeczy - referencję na konstruktor oraz listę parametrów dla konstruktora. Tak samo z anonimową funkcją

Kod: Zaznacz cały
new (function () {})()


"(function () {})" to referencja na konstruktor, "()" to pusta lista parametrów dla konstruktora.
Avatar użytkownikakuku
Rafał Kukawski

+∞
+∞

Posty: 19640
Dołączył(a): 14.04.2002

Re: operator new + self-invoking functions

Post 10.11.2017, 17:05:32

Dziękuję za odpowedź Kuku.

W takim wypadku prosiłbym Cię o przykład wykorzystania parametrów dla konstruktora np. new (function () {})().

Bo generalnie jest tak, że definiując klasę, podaje jakich parametrow bede oczekiwał, a nastepnie przekazuje te dane jako parametry instancji danej klasy.

Natomiast tutaj mamy argumenty bezpośrednio dla konstruktora - bez wykorzystania instancji. Stąd mały mętlik.

Pozdrawiam!
whitty
Posty: 88
Dołączył(a): 12.07.2015

Re: operator new + self-invoking functions

Post 10.11.2017, 19:15:26

whitty napisał(a):W takim wypadku prosiłbym Cię o przykład wykorzystania parametrów dla konstruktora np. new (function () {})().

niestety nadal nie rozumiem.

Mogę dać coś takiego

Kod: Zaznacz cały
var obj = new (function (x, y, z) {
  this.a = x;
  this.b = y;
  this.c = z;
})(1,2,3);

console.log(obj.a, obj.b, obj.c); // 1,2,3


[...] bez wykorzystania instancji. Stąd mały mętlik.

mam wrażenie, że nie do końca rozumiesz pojęć klasy i instancji.

Weźmy Javę (bo tam mamy klasowy model obiektowy).

Kod: Zaznacz cały
class Klasa {
  public Klasa () {
    // ciało konstruktora klasy
  }
}

Klasa instancja = new Klasa();


Mamy klasę o nazwie Klasa. Instancją klasy Klasa jest wynik operacji new Klasa.

W JS mamy pewną analogię

Kod: Zaznacz cały
function Klasa() {
  // ciało konstruktora klasy
}

var instancja = new Klasa();


W JS odpowiednikiem Javovej klasy jest konstruktor (który technicznie jest zwykłą funkcją). Instancją jest wynik działania operatora new. I będzie to instancja konstruktora Klasa.

Konstruktor może oczekiwać parametrów. Konstruktor może użyć tych parametrów do przygotowania stanu instancji

Kod: Zaznacz cały
function Animal(kind) {
  // instancja Konstruktora Animal została utworzona przez operator new i przekazana do konstruktora jako "this"
  // dlatego możemy wykonywać na niej operacje
  // np. przypisać własność "kind" na wartość jaką otrzymał konstruktor w parametrze
  this.kind = kind;
}

var dog = new Animal('dog');
var cat = new Animal('car');
console.log(dog.kind, cat.kind); // "dog", "cat"


Wracając teraz do Twojego kodu
Kod: Zaznacz cały
new (function(){})();

Ten kod definiuje anonimowego konstruktora, który nie oczekuje żadnych parametrów. W wywołaniu new nie przekazujesz też żadnych parametrów do niego. Technicznie, ten kod jest identyczny z

Kod: Zaznacz cały
var AnonimowyKonstruktor = function () {};
new AnonimowyKonstruktor();

tyle, że nie ma w nim deklaracji zmiennej AnonimowyKonstruktor.
Avatar użytkownikakuku
Rafał Kukawski

+∞
+∞

Posty: 19640
Dołączył(a): 14.04.2002


Powrót do JavaScript


 


  • Podobne wątki
    Odpowiedzi
    Wyświetlone
    Ostatni post

Kto przegląda forum

Użytkownicy przeglądający ten dział: Ahrefs [Bot], Yandex [Bot] i 8 gości

Hosting, Domeny, SSL

Subskrypcja

Mamy 50671 zarejestrowanych użytkowników.
Najnowszy użytkownik: JustinSt


Nasi użytkownicy napisali:

  • 936052 wiadomości
  • w 246709 tematach

Najnowsze wpisy na blogu

Najnowsze artykuły

Najaktywniejsi (ostatnie 30 dni)