Odnosnik do obiektu tworzy nowy osobny obiekt?!

0

Witajcie, jesttem w miare nowy w nodejs ale pewna przypadlosc nodejs mnie przerazila....
jest sobie taki kod:

getOrdersToDo(newOrders)
    {
        let ordersToDoArr = [];

        this.activeOrders.map((activeOrderChain, activeIndex) => {
            let isInNewOrders = false;
            newOrders.map((newChain, newIndex) =>{
                if(activeOrderChain.makerId === newChain.makerId)
                {
                    isInNewOrders = true;
                    let slicedNewChain = newOrders.splice(newIndex, 1)[0];
                    if(activeOrderChain.getMakerStep().price !== newChain.getMakerStep().price)
                        ordersToDoArr.push(this.getUpdatedOrder(activeIndex, slicedNewChain));
                }
            })
.........

    getUpdatedOrder(activeIndex, newChain)//activeChain, newChain)
    {
        let activeChain = self.activeOrders[activeIndex];
        let newMakerStep = newChain.getMakerStep();
        newMakerStep.orderId = activeChain.getMakerStep().orderId;
        newMakerStep.status = "toChange";
        newMakerStep.callback = this.updateOrderIdCallback;
        newMakerStep.gamePrice += this.addFragmentPrice(newMakerStep.type, newMakerStep.price);
        self.activeOrders[activeIndex] = newChain;
        return activeChain.getMakerStep();
    }

Dziala poprawnie. Jesli natomiast metode getUpdatedOrder zmodyfikuje w ten sposob:

    getUpdatedOrder(activeIndex, newChain)//activeChain, newChain)
    {
        let activeChain = self.activeOrders[activeIndex];
        let newMakerStep = newChain.getMakerStep();
        newMakerStep.orderId = activeChain.getMakerStep().orderId;
        newMakerStep.status = "toChange";
        newMakerStep.callback = this.updateOrderIdCallback;
        newMakerStep.gamePrice += this.addFragmentPrice(newMakerStep.type, newMakerStep.price);
        activeChain = newChain; // **<<<---- !!!!!!!!!!!!**
        return activeChain.getMakerStep();
    }

To teraz jesli sie tam zdebuguje i sprawdze self.activeOrders, to wychodzi ze polecenie activeChain = newChain; nie wplywa na obiekt w tablicy tylko tak jakby polecenie let activeChain = self.activeOrders[activeIndex]; tworzylo NOWY obiekt a nie tylko powiazanie do juz istniejacego.... Innymi slowy activeChain to newChain ale w self.activeOrders[jakisIndexobiektuActiveChain] jest dalej stary chain bez zmian WTF??!!

3

To żaden WTF. activeChain = newChain zastępuje odniesienie do obiektu pobranego z tablicy, odniesieniem do obiektu newChain. Tutaj już o tym pisałem: Przekazywanie argumentów do funkcji przez referencję (pierwsze dwa listingi).

Jeżeli zrobisz:

activeChain.dupa = 'asd';

to w rzeczy samej zmodyfikujesz obiekt, który znajduje się w tablicy. Jeżeli natomiast przypiszesz do zmiennej activeChain inną wartość, to od teraz ta zmienna będzie trzymała odniesienie do nowego obiektu, a stary pozostanie nienaruszony. Generalnie sporo języków w ten sposób działa. Jeżeli chcesz zmodyfikować coś w sposób z drugiego listingu, to w innych językach musisz użyć pointerów (języki z rodziny C, Go).

@goku21 To działa mniej więcej tak:
Webp.net-gifmaker.gif

Dopiero arr[0] = jim zmienia tablicę. Na samym końcu john znika z pamięci, bo ostatnie odniesienie do niego zostało zastąpione :)

0

Dzieki za odpowiedz :)

Czyli wlasciwosci mozemy modyfikowac. Mozemy zrobic np cos takiego:
Class1

constructor(){
     this.arr1 = [1,2,3];
}

Class2
constructor(arr)
{
    this.arr2 = arr;
   this.add(4);
}

add(num)
{
  this.arr2.push(num);
}

tutaj i tablica w class1 bedzie miala wartosc [1,2,3,4] i tablica w class2 bedzie miala ta sama wartosc poniewaz arr2 jest w sumie referencja do tablicy arr1? Natomiast jesli napisze arr2 = []; to po prostu zmienie referencje zmiennej arr2 do nowej pustej tablicy a arr1 w class1 pozostanie bez zmian. W sumie fakt heh czasami czlowiek slepnie;p

Moim zdaniem najwieksza bolaczka javascript jest brak wymuszania typow, klasy bez zmiennych prywatnych, brak interfejsow.

1

Moim zdaniem najwieksza bolaczka javascript jest brak wymuszania typow, klasy bez zmiennych prywatnych, brak interfejsow.

Zbyt daleko posunięte wnioski.

Przykłady, które podałeś raczej jeśli już, to są argumentem za tym, że w JS najlepiej po prostu by było nie zmieniać ani obiektów, ani tablic, a traktować wszystko jak niezmienne (immutable). I dzięki temu nie byłoby strachu, że klasa B będzie zmieniać tablicę należącą do klasy A. Bo zamiast modyfikować, to tworzyłbyś nową tablicę zmapowaną/przefiltrowaną/itp.

I dlatego właśnie programowanie funkcyjne jest tak popularne w JS (chociaż moim zdaniem aż za bardzo popularne, ludzie w dogmatyzm popadają).

0

Oj cos mi tu nie pasuje :) Zalozmy ze mam obiekty ktore moga byc w stanie a,b,c. I jak tu teraz nie przełączać obiekty miedzy stanami tylko traktowac raz przypisany stan do obiektu jako niezmienialny?:>
Ok mozesz tworzyc nowy obiekt ze zmienianym stanem ale czy na pewno o to chodzi zeby kazda "zmienna" byla publiczna, globalna stałą?

0

No, zwykle się po prostu tworzy nowy obiekt, który jest taki sam jest poprzedni, tylko, że ma np. 1 właściwość inną.

I jak tu teraz nie przełączać obiekty miedzy stanami tylko traktowac raz przypisany stan do obiektu jako niezmienialny?:

czy na pewno o to chodzi zeby kazda "zmienna" byla publiczna, globalna stałą?

Nie musi być globalna, możesz wstrzykiwać obiekty do funkcji jako parametry. Tym sposobem jakaś funkcja będzie widziała tylko dane wcielenie obiektu.

Np. tak:

let currentState

function foo(state) {
      // .........
}
currentState = {a: 123};
foo(state);

currentState = {a: 245};
foo(state);

można się też umówić tak, że funkcja zwraca nową wartość stanu (tak działa Redux):


let currentState = [];

function foo(state) {
     // zwracamy nową wartość stanu, ale nie zmieniamy jego,
     // bo concat tworzy nową tablicę
     return state.concat('kotek'); 
}
currentState = foo(state);
currentState = foo(state);
currentState = foo(state);

I są też inne podejścia.

1 użytkowników online, w tym zalogowanych: 0, gości: 1