Πώς να πάρετε μια ιδέα για την αναφορά έναντι της τιμής στο JavaScript

Αυτό το άρθρο περιγράφει τον τρόπο συμπεριφοράς των διαφόρων τύπων δεδομένων JavaScript όταν έχουν αντιστοιχιστεί σε μια μεταβλητή. Ανάλογα με τον τύπο δεδομένων, η μνήμη κατανέμεται διαφορετικά για την αποθήκευσή της. Μπορεί να δεσμεύσει έναν νέο χώρο για να αποθηκεύσει ένα αντίγραφο της τιμής ή μπορεί να μην δημιουργήσει ένα αντίγραφο καθόλου και απλά να δείξει την υπάρχουσα τιμή (αναφορά).
Ακολουθούν οι σημειώσεις μου που ακολούθησαν το μάθημα Javascript30 του Wes Bos
Αριθμοί, χορδές και Booleans
Σε JavaScript, πρωτόγονων τύπων όπως undefined
, null
, string
, number
, boolean
και symbol
έχουν περάσει από την αξία.
let name = ‘Marina’;let name2 = name;
console.log({name, name2}); >> { name: ‘Marina’, name2: ‘Marina’ }
name = ‘Vinicius’;
console.log({name, name2});>> { name: ‘Vinicius’, name2: ‘Marina’ }

Όταν name
εκχωρηθεί η μεταβλητή, δεσμεύεται ένα κενό στη μνήμη με διεύθυνση του 0x001
για να αποθηκεύσει αυτήν την τιμή. Στη name
συνέχεια, η μεταβλητή δείχνει αυτήν τη διεύθυνση. Η μεταβλητή name2
ρυθμίζεται έπειτα στο ίδιο name
. Ένας νέος χώρος στη μνήμη, με μια νέα διεύθυνση 0x002
εκχωρείται και αποθηκεύει ένα αντίγραφο της τιμής που είναι αποθηκευμένη στη διεύθυνση στα name
σημεία.
Έτσι, όποτε θέλουμε να τροποποιήσουμε την τιμή name
, η τιμή που αποθηκεύεται από name2
δεν θα αλλάξει, δεδομένου ότι είναι αντίγραφο, αποθηκευμένη σε διαφορετική τοποθεσία.
Αντικείμενα και πίνακες
Τα αντικείμενα σε JavaScript περνούν με αναφορά. Όταν περισσότερες από μία μεταβλητές έχουν ρυθμιστεί για αποθήκευση είτε ενός object
, array
είτε function
, αυτές οι μεταβλητές θα δείχνουν στον ίδιο εκχωρημένο χώρο στη μνήμη.
const animals = ['Cat', 'Dog', 'Horse', 'Snake'];
let animals2 = animals;console.log({animals, animals2});>>{ animals: ['Cat', 'Dog', 'Horse', 'Snake'], animals2: ['Cat', 'Dog', 'Horse', 'Snake']}
animals2[3] = 'Wale';console.log(animals, animals2);>>{ animals: ['Cat', 'Dog', 'Horse', 'Wale'], animals2: ['Cat', 'Dog', 'Horse', 'Wale']}

Όταν animals
έχει ρυθμιστεί να αποθηκεύει έναν πίνακα, εκχωρείται μνήμη και μια διεύθυνση συσχετίζεται με αυτήν τη μεταβλητή. Στη συνέχεια animals2
ορίζεται στο ίδιο animals
. Δεδομένου ότι animals
αποθηκεύει έναν πίνακα, αντί να δημιουργεί ένα αντίγραφο αυτού του πίνακα και μια νέα διεύθυνση στη μνήμη, animals2
απλώς επισημαίνεται στο ίδιο αντικείμενο στην υπάρχουσα διεύθυνση. Με αυτόν τον τρόπο τυχόν αλλαγές που γίνονται animals2
θα προβληματιστούν animals
, επειδή δείχνουν στην ίδια τοποθεσία.
Θα δείτε την ίδια συμπεριφορά για αντικείμενα:
const person = { name: 'Marina', age: 29};
let femme = person;femme.age = 18;
console.log({person, femme});>>{ person: { name: 'Marina', age: 18 }, femme: { name: 'Marina', age: 18 }}
Αντιγραφή αντικειμένων και συστοιχιών
Δεδομένου ότι μια απλή ανάθεση δεν αρκεί για την παραγωγή αντιγράφου ενός αντικειμένου, αυτό μπορεί να επιτευχθεί με άλλες προσεγγίσεις:
Πίνακες
φέτα()
let animals2 = animals.slice();animals2[3] = 'Shark';
συμπυκνωμένος ()
let animals3 = [].concat(animals);animals3[3] = 'Tiger';
spread (ES6)
let animals4 = [...animals];animals4[3] = 'Lion';
Οι αλλαγές θα επηρεάσουν μόνο το αντικείμενο που τροποποιήθηκε:
console.log({animals, animals2, animals3, animals4});>>{ animals: ['Cat', 'Dog', 'Horse', 'Snake'], animals2: ['Cat', 'Dog', 'Horse', 'Shark'], animals3: ['Cat', 'Dog', 'Horse', 'Tiger'], animals4: ['Cat', 'Dog', 'Horse', 'Lion']}
Αντικείμενα
αναθέτω()
let human = Object.assign({}, person, { age: 20 });
console.log(person, human);>>{ person: { name: 'Marina', age: 29 }, human: { name: 'Marina', age: 20 }}
Βαθιά κλώνος
Είναι σημαντικό να σημειωθεί ότι αυτές οι μέθοδοι έχουν βάθος μόνο ενός επιπέδου. Για βαθιά κλώνους υπάρχει μια μέθοδος frown on. Χρησιμοποιήστε προσεκτικά.
let femme3 = JSON.parse(JSON.stringify(person));femme3.name = 'Leslie';
console.log(person, femme3);>>{ person: { name: 'Marina', age: 29 }, femme3: { name: 'Leslie', age: 29 }}
βιβλιογραφικές αναφορές
- WesBos - Javascript 30
- Δεν ξέρετε JS: Scope & Closures από τον Kyle Simpson
Αρχικά δημοσιεύθηκε στο marina-ferreira.github.io.