Mutabilità e pass-by-reference, oggetto "nuovo", cosa ho lasciato fuori?

0

Ho iniziato a mettere in discussione ciò che so, o ho pensato che lo so, dopo questa domanda:

Array.fill si differenzia dalla definizione letterale 2D sull'assegnazione

Una domanda JavaScript, che definisce una matrice con lunghezza predefinita e la riempie di valori, quindi modifica uno dei valori all'interno della seconda dimensione.

Mutabilità , in questo caso applicato, il primo nuovo array (9) sarà il mio oggetto, contenente un array vuoto ([]) , con una lunghezza predefinita di 9. E il primo che segue .fill () sarà il metodo mutable chiamato, rendendo l'oggetto referenced ([]) in qualunque cosa desiderata venga riempita ([ ..., ..., ..., ...]) , mantenendo la lunghezza. In questo caso, se provo questo su un array a dimensione singola, tutto andrà bene, farò riferimento all'oggetto principale stesso e ad aggiornare i valori di esso di conseguenza con le sue chiavi.

Se prendo questo nella seconda dimensione, immagino che questa sia la parte di cui principalmente non mi occupo, ora sto invece riempiendo l'array vuoto di 9 lunghezze iniziali ([]) con un nuovo singolo Array vuoto di 9 lunghezze riempite con 9 zeri , per ogni indice riempito fino all'ultimo, ma non sembra?

Invece, il nuovo riferimento sembra non essere considerato, o contato come un nuovo oggetto , ma più come un semplice riferimento. Proprio come questo:

var arr1 = new Array(9).fill(0);
var arr2 = new Array(9).fill(arr1);

Quindi, sto riempiendo nove riferimenti alla prima, prima dimensione. Quindi, se aggiorno il 3 ° o 4 ° indice non è importante, poiché tutti puntano allo stesso riferimento e aggiornano il valore arr1 del riferimento all'indice specificato.

Che cosa mi manca qui che causa il passaggio di riferimenti al posto di un nuovo oggetto come pensavo?

    
posta Ketchup God 03.02.2016 - 18:31
fonte

1 risposta

1

Grazie al rapido suggerimento nei commenti di @ Jörg W Mittag, ho capito cosa stavo saltando. Sto chiamando la nuova matrice (...) nel metodo di riempimento, come una variabile, in ogni caso. Ciò che è diverso in questa 'variabile' è che, a differenza di uno come una stringa, o di un intero, che sono corrispondentemente i loro valori per i propri tipi, in questo caso, il valore di un oggetto è il suo riferimento. Semplificando l'idea, l'ho capito grazie a questo riferimento esplicativo visivo pass-by-value :

Cat A = new Cat();
doStuff(A);

void doStuff(Cat B) {
    // use B in some way
}

In questo codice, il riferimento di A viene passato alla funzione doStuff (simile al metodo di riempimento che stavo usando inizialmente), quindi diventa B all'interno del suo ambito, facendo comunque riferimento allo stesso oggetto iniziale, A, dovuto a come funzionano gli oggetti e fanno riferimento al di fuori dell'ambito delle modifiche. Come menzionato dal link sopra, diventano semplicemente due diversi controller remoti per lo stesso oggetto.

Ho applicato la stessa logica e ho cercato di accertarmi di come qualcosa di simile avrebbe funzionato nel luogo originale su cui stavo lavorando, ed eccoli qui:

    /*
     * initiate a 9 length array on-the-fly, 
     * fill all the values equal to 0, 
     * send the newly created object into doStuff1 on-the-fly, 
     * log the return of it.
     * console prints out with changed value(Let's say we're not sure at this point the reference carries on).
     */ 

    function doStuff1(b){
        b[3] = 1;
        return b;
    }

    console.log(doStuff1(new Array(9).fill(0)));

    /*
     * initiate a 9 length array, on a variable named 'a',
     * fill all the values equal to 0,
     * send the newly created object into doStuff2,
     * log the variable 'a'.
     * console prints out with changed value('a' variable held the reference into the function, 
     * and carried back it's process outside the scope, proven).
     */
    var a = new Array(9).fill(0);

    function doStuff2(b){
        b[3] = 1;
    }

    doStuff2(a);
    console.log(a);

Gli oggetti passano con i loro riferimenti o copiano i loro riferimenti come passano le variabili di tipo (come int, byte) o ne copia i valori. Finché il loro riferimento rimane, saranno mutabili, perché il passaggio di una variabile in una funzione sarà immutabile e solo una copia del loro valore sarà assegnata all'ambito della funzione, a meno che ulteriori modifiche interne rimangano all'interno dello scope, a meno che la variabile dell'ambito esterno viene riferita direttamente.

    var a = "hello";

    function doStuff(b){
        //no change to a, since b was a copy-value
        b = "hi";
        //direct reference to the original variable, outer scope value changed
        a = "welcome";  
        //b wasn't present until this function was called, and will be dismissed after
        console.log(b); 
    }
    doStuff(a);
    //outer scope var which was changed through doStuff by direct reference
    console.log(a);  
    
risposta data 03.02.2016 - 20:17
fonte

Leggi altre domande sui tag