Skip to content
Skip to content
Menu
Info Cafe
Info Cafe

Objecten kopiëren in JavaScript

By admin on januari 10, 2021

Objecten zijn de fundamentele blokken van JavaScript. Een object is een verzameling eigenschappen, en een eigenschap is een associatie tussen een sleutel (of naam) en een waarde. Bijna alle objecten in JavaScript zijn instanties van Object, dat bovenaan de prototype-keten staat.

Inleiding

Zoals je weet, maakt de toewijzingsoperator geen kopie van een object, het wijst er alleen een verwijzing naar toe, laten we eens kijken naar de volgende code:

let obj = { a: 1, b: 2,};let copy = obj;obj.a = 5;console.log(copy.a);// Result // a = 5;

De obj variabele is een container voor het nieuwe object dat geïnitialiseerd is. De copy variabele wijst naar hetzelfde object en is een verwijzing naar dat object. Dus eigenlijk zegt dit { a: 1, b: 2, } object: Er zijn nu twee manieren om toegang tot mij te krijgen. Je moet door de obj variabele of de copy variabele heen hoe dan ook je komt nog steeds bij mij en alles wat je via deze manieren (gateways) met mij doet zal mij beïnvloeden.

Immuteerbaarheid wordt tegenwoordig veel over gesproken en je moet naar deze oproep luisteren! Deze methode verwijdert elke vorm van onveranderlijkheid en zou tot bugs kunnen leiden als het originele object door een ander deel van je code wordt gebruikt.

De naïeve manier van objecten kopiëren

De naïeve manier van objecten kopiëren is door het originele object te lussen en elke eigenschap de een na de ander te kopiëren. Laten we eens naar deze code kijken:

function copy(mainObj) { let objCopy = {}; // objCopy will store a copy of the mainObj let key; for (key in mainObj) { objCopy = mainObj; // copies each property to the objCopy object } return objCopy;}const mainObj = { a: 2, b: 5, c: { x: 7, y: 4, },}console.log(copy(mainObj));

Inherente problemen

  1. objCopy object heeft een nieuwe Object.prototype methode die verschilt van de mainObj object prototype methode, en dat is niet wat we willen. We willen een exacte kopie van het originele object.
  2. Eigenschapdescriptors worden niet gekopieerd. Een “writable” descriptor met waarde false wordt true in het objCopy object.
  3. De bovenstaande code kopieert alleen enumerable properties van mainObj.
  4. Als een van de properties in het originele object zelf een object is, dan wordt het gedeeld tussen de kopie en het origineel waardoor hun respectievelijke properties naar hetzelfde object wijzen.

Slim kopiëren van objecten

Een object wordt ondiep gekopieerd als de top-level bron-eigenschappen worden gekopieerd zonder enige verwijzing en er een bron-eigenschap bestaat waarvan de waarde een object is en wordt gekopieerd als een verwijzing. Als de bronwaarde een verwijzing naar een object is, wordt alleen die referentiewaarde gekopieerd naar het doelobject.

Een ondiepe kopie zal de eigenschappen op het hoogste niveau dupliceren, maar het geneste object wordt gedeeld tussen het origineel(bron) en de kopie(doel).

Gebruik van de Object.assign() methode

De Object.assign() methode wordt gebruikt om de waarden van alle telbare eigen eigenschappen van een of meer bron-objecten naar een doel-object te kopiëren.

let obj = { a: 1, b: 2,};let objCopy = Object.assign({}, obj);console.log(objCopy);// Result - { a: 1, b: 2 }

Wel, dit doet het werk tot nu toe. We hebben een kopie gemaakt van obj. Laten we eens kijken of onveranderlijkheid bestaat:

let obj = { a: 1, b: 2,};let objCopy = Object.assign({}, obj);console.log(objCopy); // result - { a: 1, b: 2 }objCopy.b = 89;console.log(objCopy); // result - { a: 1, b: 89 }console.log(obj); // result - { a: 1, b: 2 }

In de bovenstaande code, hebben we de waarde van de eigenschap 'b' in objCopy object veranderd in 89 en wanneer we het gewijzigde objCopy object in de console loggen, gelden de veranderingen alleen voor objCopy. De laatste lijn van de code controleert of het obj object nog intact is en niet veranderd is. Dit betekent dat we met succes een kopie van het bronobject hebben gemaakt zonder verwijzingen ernaar.

Pitfall of Object.assign()

Niet zo snel! We hebben met succes een kopie gemaakt en alles lijkt goed te werken, maar weet je nog dat we het hadden over ondiep kopiëren? Laten we eens naar dit voorbeeld kijken:

let obj = { a: 1, b: { c: 2, },}let newObj = Object.assign({}, obj);console.log(newObj); // { a: 1, b: { c: 2} }obj.a = 10;console.log(obj); // { a: 10, b: { c: 2} }console.log(newObj); // { a: 1, b: { c: 2} }newObj.a = 20;console.log(obj); // { a: 10, b: { c: 2} }console.log(newObj); // { a: 20, b: { c: 2} }newObj.b.c = 30;console.log(obj); // { a: 10, b: { c: 30} }console.log(newObj); // { a: 20, b: { c: 30} }// Note: newObj.b.c = 30; Read why..

Waarom is obj.b.c = 30?

Wel, dat is een valkuil van Object.assign()Object.assign maakt alleen ondiepe kopieën. Zowel newObj.b als obj.b delen dezelfde referentie naar het object omdat er geen individuele kopieën werden gemaakt, maar een referentie naar het object werd gekopieerd. Elke wijziging aan een eigenschap van het object geldt voor alle verwijzingen die het object gebruiken. Hoe kunnen we dit oplossen? Lees verder… we hebben een oplossing in de volgende sectie.

Note: Eigenschappen op de prototype-keten en niet-telbare eigenschappen kunnen niet worden gekopieerd. Zie hier:

let someObj = { a: 2,}let obj = Object.create(someObj, { b: { value: 2, }, c: { value: 3, enumerable: true, },});let objCopy = Object.assign({}, obj);console.log(objCopy); // { c: 3 }

  • someObj staat op obj’s prototype-keten en zou dus niet worden gekopieerd.
  • property b is een niet-telbare property.
  • property c heeft een enumerable property descriptor waardoor het wel telbaar is. Daarom is het gekopieerd.

Diep kopiëren van objecten

Een diepe kopie zal elk object dat het tegenkomt dupliceren. De kopie en het originele object zullen niets delen, dus zal het een kopie van het origineel zijn. Hier is de oplossing voor het probleem dat we tegenkwamen met Object.assign(). Laten we eens kijken.

Gebruik JSON.parse(JSON.stringify(object));

Dit lost het probleem op dat we eerder hadden. Nu heeft newObj.b een kopie en geen referentie! Dit is een manier om objecten diep te kopiëren. Hier is een voorbeeld:

let obj = { a: 1, b: { c: 2, },}let newObj = JSON.parse(JSON.stringify(obj));obj.b.c = 20;console.log(obj); // { a: 1, b: { c: 20 } }console.log(newObj); // { a: 1, b: { c: 2 } } (New Object Intact!)

Immutable: ✓

Pitfall

Gelukkig genoeg kan deze methode niet worden gebruikt om door de gebruiker gedefinieerde object methoden te kopiëren. Zie hieronder.

Kopiëren van objectmethoden

Een methode is een eigenschap van een object die een functie is. In de voorbeelden tot nu toe hebben we nog geen object met een methode gekopieerd. Laten we dat nu eens proberen en de methoden die we hebben geleerd gebruiken om kopieën te maken.

let obj = { name: 'scotch.io', exec: function exec() { return true; },}let method1 = Object.assign({}, obj);let method2 = JSON.parse(JSON.stringify(obj));console.log(method1); //Object.assign({}, obj)/* result{ exec: function exec() { return true; }, name: "scotch.io"}*/console.log(method2); // JSON.parse(JSON.stringify(obj))/* result{ name: "scotch.io"}*/

Het resultaat laat zien dat Object.assign() gebruikt kan worden om methoden te kopiëren, terwijl JSON.parse(JSON.stringify(obj)) niet gebruikt kan worden.

Copying Circular Objects

Circulaire objecten zijn objecten die eigenschappen hebben die naar zichzelf verwijzen. Laten we de methoden voor het kopiëren van objecten die we tot nu toe hebben geleerd gebruiken om kopieën te maken van een cirkelvormig object en kijken of het werkt.

Gebruik JSON.parse(JSON.stringify(object))

Laten we JSON.parse(JSON.stringify(object)) proberen:

// circular objectlet obj = { a: 'a', b: { c: 'c', d: 'd', },}obj.c = obj.b;obj.e = obj.a;obj.b.c = obj.c;obj.b.d = obj.b;obj.b.e = obj.b.c;let newObj = JSON.parse(JSON.stringify(obj));console.log(newObj); 

Hier is het resultaat:

JSON.parse(JSON.stringify(obj)) werkt duidelijk niet voor cirkelvormige objecten.

Gebruik Object.assign()

Laten we Object.assign() eens proberen:

// circular objectlet obj = { a: 'a', b: { c: 'c', d: 'd', },}obj.c = obj.b;obj.e = obj.a;obj.b.c = obj.c;obj.b.d = obj.b;obj.b.e = obj.b.c;let newObj2 = Object.assign({}, obj);console.log(newObj2); 

Hier is het resultaat:

Object.assign() werkt prima voor het ondiep kopiëren van cirkelvormige objecten, maar zou niet werken voor het diep kopiëren. Voel je vrij om de circular object tree op je browser console te onderzoeken. Ik weet zeker dat je daar veel interessant werk zult vinden.

Gebruik spreidingselementen ( … )

ES6 heeft al rest-elementen voor array destructureringstoewijzing en spreidingselementen voor array-literalen geïmplementeerd. Kijk hier naar de implementatie van spread elementen op een array:

const array = ;const newArray = ;console.log(newArray);// Result // 

De spread eigenschap voor object-literals is momenteel een Stage 3 voorstel voor ECMAScript. Spread properties in object initializers kopieert eigen enumerable properties van een bron object naar het doel object. Het onderstaande voorbeeld laat zien hoe eenvoudig het zou zijn om een object te kopiëren als het voorstel eenmaal is aanvaard.

let obj = { one: 1, two: 2,}let newObj = { ...z };// { one: 1, two: 2 }

Note: Dit zal alleen effectief zijn voor oppervlakkig kopiëren

Conclusie

Het kopiëren van objecten in JavaScript kan behoorlijk ontmoedigend zijn, vooral als je nieuw bent in JavaScript en je weg in de taal niet kent. Hopelijk heeft dit artikel je geholpen het te begrijpen en toekomstige valkuilen te vermijden die je kunt tegenkomen bij het kopiëren van objecten. Als je een bibliotheek of stuk code hebt dat een beter resultaat oplevert, voel je dan welkom om het met de gemeenschap te delen. Veel plezier met coderen

Berichtnavigatie

Kroger Weekly Ad (2/24/21 – 3/21) & Kroger Ad Preview Sneak Peek
Hoe maak je een opstartbare CD/DVD/USB om Windows te installeren

Geef een reactie Antwoord annuleren

Het e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *

Meest recente berichten

  • 9 Beste Vitaminen en Supplementen voor honden voor een betere gezondheid
  • CD-rentevoorspelling voor 2021: Tarieven blijven waarschijnlijk laag, maar kunnen later in het jaar stijgen
  • Hoe de documentatie van het kwaliteitsmanagementsysteem te structureren
  • Chronische bekkenpijn en prostatitis: symptomen, diagnose en behandeling
  • Mixed Berry Crisp
  • Koolhydraatarm chocoladepuddingrecept
  • Gezonde spelletjes en activiteiten voor kinderen | UIC Online Informatics
  • De voordelen van borstvoeding na één jaar
  • Is het veilig om koffiedik door de gootsteen te spoelen | Atomic Plumbing
  • Onze werkzaamheden

Meta

  • Inloggen
  • Berichten feed
  • Reacties feed
  • WordPress.org

Archief

  • maart 2021
  • februari 2021
  • januari 2021
  • december 2020
  • DeutschDeutsch
  • NederlandsNederlands
  • EspañolEspañol
  • FrançaisFrançais
  • PortuguêsPortuguês
  • ItalianoItaliano
  • PolskiPolski
  • 日本語日本語
©2021 Info Cafe | WordPress Theme by SuperbThemes.com