maszynopis - klonowanie obiektu

187

Mam klasy, która jest super-rodzic ( Entity) dla wielu podklasy ( Customer, Product, ProductCategory...)

Chcę dynamicznie sklonować obiekt, który zawiera różne obiekty podrzędne w Typescript.

Na przykład: a Customerktóry ma inny, Productkto maProductCategory

var cust:Customer  = new Customer ();

cust.name = "someName";
cust.products.push(new Product(someId1));
cust.products.push(new Product(someId2));

Aby sklonować całe drzewo obiektu stworzyłem funkcję w Entity

public clone():any {
    var cloneObj = new this.constructor();
    for (var attribut in this) {
        if(typeof this[attribut] === "object"){
           cloneObj[attribut] = this.clone();
        } else {
           cloneObj[attribut] = this[attribut];
        }
    }
    return cloneObj;
}

Po newtranspozycji do javascript pojawia się następujący błąd:error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature.

Chociaż skrypt działa, chciałbym pozbyć się transpiltowanego błędu

David Laberge
źródło

Odpowiedzi:

255

Rozwiązywanie konkretnego problemu

Możesz użyć potwierdzenia typu, aby powiedzieć kompilatorowi, że wiesz lepiej:

public clone(): any {
    var cloneObj = new (this.constructor() as any);
    for (var attribut in this) {
        if (typeof this[attribut] === "object") {
            cloneObj[attribut] = this[attribut].clone();
        } else {
            cloneObj[attribut] = this[attribut];
        }
    }
    return cloneObj;
}

Klonowanie

Pamiętaj, że czasami lepiej jest napisać własne mapowanie, niż być całkowicie dynamicznym. Jest jednak kilka sztuczek „klonowania”, których możesz użyć, a które dają różne efekty.

Dla wszystkich kolejnych przykładów użyję następującego kodu:

class Example {
  constructor(public type: string) {

  }
}

class Customer {
  constructor(public name: string, public example: Example) {

  }

  greet() {
    return 'Hello ' + this.name;
  }
}

var customer = new Customer('David', new Example('DavidType'));

Opcja 1: Spread

Właściwości: Tak
Metody: Nie
Głęboka kopia: Nie

var clone = { ...customer };

alert(clone.name + ' ' + clone.example.type); // David DavidType
//alert(clone.greet()); // Not OK

clone.name = 'Steve';
clone.example.type = 'SteveType';

alert(customer.name + ' ' + customer.example.type); // David SteveType

Opcja 2: Object. assign

Właściwości: Tak
Metody: Nie
Głęboka kopia: Nie

var clone = Object.assign({}, customer);

alert(clone.name + ' ' + clone.example.type); // David DavidType
alert(clone.greet()); // Not OK, although compiler won't spot it

clone.name = 'Steve';
clone.example.type = 'SteveType';

alert(customer.name + ' ' + customer.example.type); // David SteveType

Opcja 3: Object.create

Właściwości: Metody dziedziczone
: Dziedziczone
Głębokie kopie: Płytkie Dziedziczone (głębokie zmiany wpływają na oryginał i klon)

var clone = Object.create(customer);

alert(clone.name + ' ' + clone.example.type); // David DavidType
alert(clone.greet()); // OK

customer.name = 'Misha';
customer.example = new Example("MishaType");

// clone sees changes to original 
alert(clone.name + ' ' + clone.example.type); // Misha MishaType

clone.name = 'Steve';
clone.example.type = 'SteveType';

// original sees changes to clone
alert(customer.name + ' ' + customer.example.type); // Misha SteveType

Opcja 4: Funkcja głębokiego kopiowania

Właściwości: Tak
Metody: Nie
Głęboka kopia: Tak

function deepCopy(obj) {
    var copy;

    // Handle the 3 simple types, and null or undefined
    if (null == obj || "object" != typeof obj) return obj;

    // Handle Date
    if (obj instanceof Date) {
        copy = new Date();
        copy.setTime(obj.getTime());
        return copy;
    }

    // Handle Array
    if (obj instanceof Array) {
        copy = [];
        for (var i = 0, len = obj.length; i < len; i++) {
            copy[i] = deepCopy(obj[i]);
        }
        return copy;
    }

    // Handle Object
    if (obj instanceof Object) {
        copy = {};
        for (var attr in obj) {
            if (obj.hasOwnProperty(attr)) copy[attr] = deepCopy(obj[attr]);
        }
        return copy;
    }

    throw new Error("Unable to copy obj! Its type isn't supported.");
}

var clone = deepCopy(customer) as Customer;

alert(clone.name + ' ' + clone.example.type); // David DavidType
// alert(clone.greet()); // Not OK - not really a customer

clone.name = 'Steve';
clone.example.type = 'SteveType';

alert(customer.name + ' ' + customer.example.type); // David DavidType
Fenton
źródło
Zamknij, transpile przestał narzekać z maszynopisem 1.3, ale raz w javascript generował błąd. Maszynopis 1.4.1, nie odpuści.
David Laberge
1
Czy byłbyś abelem, aby wyjaśnić, jak dokładnie tego używasz? I włączone jako metoda mojego obiektu, a następnie dostał się błąd mówiąc, nie jest to funkcja ...
megalucio
1
Otrzymuję następujący błąd: „ERROR TypeError: this.constructor (...) is not a constructor”
michali
3
Czy właśnie zrobiłeś publiczny przykład z tego klienta?
Blair Connolly
1
Czy ktoś może dla mnie TL; DR, które z rozwiązań podanych we wszystkich odpowiedziach zachowuje typ OO klona, ​​czyli cloned instanceof MyClass === true?
Szczepan Hołyszewski
177

1. Użyj operatora rozprzestrzeniania

const obj1 = { param: "value" };
const obj2 = { ...obj1 };

Operator rozłożenia pobiera wszystkie pola z obj1 i rozkłada je na obj2. W rezultacie otrzymujesz nowy obiekt z nowym odniesieniem i tymi samymi polami, co oryginalny.

Pamiętaj, że jest to płytka kopia, oznacza to, że jeśli obiekt jest zagnieżdżony, to jego zagnieżdżone parametry złożone będą istniały w nowym obiekcie przez to samo odniesienie.

2.Object. assign ()

const obj1={ param: "value" };
const obj2:any = Object.assign({}, obj1);

Object.function tworzy prawdziwą kopię, ale tylko własne właściwości, więc właściwości w prototypie nie będą istnieć w kopiowanym obiekcie. Jest to również płytka kopia.


3.Object.create ()

const obj1={ param: "value" };
const obj2:any = Object.create(obj1);

Object.create nie dokonuje prawdziwego klonowania , ale tworzy obiekt z prototypu. Dlatego użyj go, jeśli obiekt powinien klonować właściwości typu podstawowego, ponieważ przypisanie właściwości typu podstawowego nie jest wykonywane przez odwołanie.

Plusy Object.create to, że wszelkie funkcje zadeklarowane w prototypie będzie dostępny w naszym nowo utworzonego obiektu.


Kilka rzeczy o płytkiej kopii

Płytka kopia umieszcza w nowym obiekcie wszystkie pola starego, ale oznacza to również, że jeśli oryginalny obiekt ma pola typu złożonego (obiekt, tablice itp.), To te pola są umieszczane w nowym obiekcie z tymi samymi odniesieniami. Mutacja takiego pola w oryginalnym obiekcie zostanie odzwierciedlona w nowym obiekcie.

Może to wygląda na pułapkę, ale tak naprawdę sytuacja, w której cały złożony obiekt wymaga skopiowania, jest rzadkością. Płytka kopia ponownie wykorzysta większość pamięci, co oznacza, że ​​jest bardzo tania w porównaniu do głębokiej kopii.


Głęboka kopia

Operator rozprzestrzeniania może być przydatny w przypadku głębokiego kopiowania.

const obj1 = { param: "value", complex: { name: "John"}}
const obj2 = { ...obj1, complex: {...obj1.complex}};

Powyższy kod utworzył głęboką kopię obj1. Pole złożone „złożone” zostało również skopiowane do obj2. Pole mutacji „złożone” nie będzie odzwierciedlać kopii.

Maciej Sikora
źródło
8
Nie sądzę, żeby to było całkowicie poprawne. Object.create(obj1)tworzy nowy obiekt i przypisuje obj1 jako prototyp. Żadne z pól w obj1 nie jest kopiowane ani klonowane. Zatem zmiany w obj1 bez modyfikowania obj2 będą widoczne, ponieważ zasadniczo nie ma on żadnych właściwości. Jeśli najpierw zmodyfikujesz obj2, prototyp nie będzie widoczny dla zdefiniowanego pola, ponieważ pole obj2 o nazwie znajduje się bliżej w hierarchii.
Ken Rimple,
3
Zobaczysz także, jak robią to programiści ES2015 i maszynopisu, co tworzy obiekt z pierwszego parametru (w moim przypadku pusty) i kopiuje właściwości z drugiego i kolejnych parametrów): let b = Object.assign({}, a);
Ken Rimple,
@KenRimple Masz 100% racji, dodałem więcej informacji.
Maciej Sikora
może być pomocny => developer.mozilla.org/en/docs/Web/JavaScript/Reference/ ...
Emmanuel Touzery
5
Object. assign utworzy problemy dla głębokich obiektów. Na przykład {name: 'x', values: ['a', 'b', 'c']}. Po użyciu Object. assign do klonowania, oba obiekty współdzielą tablicę wartości, więc aktualizacja jednego wpływa na drugi. Zobacz: developer.mozilla.org/en/docs/Web/JavaScript/Reference/… (sekcja „Ostrzeżenie dotyczące głębokiego klonowania”). Mówi: w przypadku głębokiego klonowania musimy użyć innych alternatyw. Dzieje się tak, ponieważ Object. assign () kopiuje odwołanie do właściwości, gdy przypisywana właściwość jest obiektem.
Meir
48

Spróbuj tego:

let copy = (JSON.parse(JSON.stringify(objectToCopy)));

Jest to dobre rozwiązanie, dopóki nie używasz bardzo dużych obiektów lub Twój obiekt nie ma właściwości, których nie można serializować.

Aby zachować bezpieczeństwo typów, możesz użyć funkcji kopiowania w klasie, z której chcesz wykonać kopie:

getCopy(): YourClassName{
    return (JSON.parse(JSON.stringify(this)));
}

lub w sposób statyczny:

static createCopy(objectToCopy: YourClassName): YourClassName{
    return (JSON.parse(JSON.stringify(objectToCopy)));
}
Lars
źródło
5
To jest w porządku, ale należy pamiętać, że podczas serializacji / analizowania utracisz informacje o prototypie i wszystkie typy nieobsługiwane w json.
Stanislav E. Govorov
1
Wydaje się to również mniej wydajne w porównaniu do funkcji deepCopy przedstawionej powyżej .
Mojtaba
Mam ten błąd: „Konwertowanie struktury cyklicznej na JSON”, gdy używam „(JSON.parse (JSON.stringify (objectToCopy)));”
Cedric Arnould
Działa tylko w 98% przypadków. Może prowadzić do brakujących kluczy z undefinedwartością przynajmniej. jeśli objectToCopy = { x : undefined};po uruchomieniu twój kod Object.keys(objectToCopy).lengthjest 1, while Object.keys(copy).lengthjest 0.
Aidin
33

TypeScript / JavaScript ma własny operator do płytkiego klonowania:

let shallowClone = { ...original };
Luca C.
źródło
15

Łatwo jest uzyskać płytką kopię dzięki „Rozkładowi obiektów” wprowadzonemu w TypeScript 2.1

ten TypeScript: let copy = { ...original };

tworzy ten JavaScript:

var __assign = (this && this.__assign) || Object.assign || function(t) {
    for (var s, i = 1, n = arguments.length; i < n; i++) {
        s = arguments[i];
        for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
            t[p] = s[p];
    }
    return t;
};
var copy = __assign({}, original);

https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-1.html

Homer
źródło
2
Uwaga: spowoduje to utworzenie płytkiej kopii
Jimmy Kane
11

Dla serializowalnego głębokiego klonu, z informacją o typie,

export function clone<T>(a: T): T {
  return JSON.parse(JSON.stringify(a));
}
Polv
źródło
1
Może to zmienić kolejność rekwizytów. Tylko ostrzeżenie dla niektórych osób. Nie obsługuje też poprawnie dat.
Pangamma
Może to zmienić kolejność rekwizytów - może spróbować npmjs.com/package/es6-json-stable-stringify zamiastJSON.stringify
Polv
@Polv, jeśli ktoś polega na kolejności kluczy w obiekcie, myślę, że ma większy problem niż clone. :)
Aidin
To rozwiązanie może pomijać klucze z undefinedwartością. Zobacz mój komentarz na temat podobnej odpowiedzi powyżej: stackoverflow.com/questions/28150967/typescript-cloning-object/…
Aidin,
7

Moje zdanie na to:

Object.assign(...) kopiuje tylko właściwości i tracimy prototyp i metody.

Object.create(...) to nie kopiowanie właściwości dla mnie i tylko tworzenie prototypu.

Udało mi się stworzyć prototyp używając Object.create(...)i kopiując do niego właściwości używając Object.assign(...):

Więc dla obiektu fooutwórz taki klon:

Object.assign(Object.create(foo), foo)
Muhammad Ali
źródło
Dzieje się tutaj bardzo subtelna rzecz. W rzeczywistości stajesz foosię prototypowym rodzicem clonedFoo(nowego obiektu). Chociaż może to zabrzmieć dobrze, należy pamiętać, że brakująca właściwość zostanie wyszukana w łańcuchu prototypów, więc const a = { x: 8 }; const c = Object.assign(Object.create(a), a); delete c.x; console.log(c.x);wypisuje 8, a powinno undefined! (Link REPL: repl.it/repls/CompetitivePreemptiveKeygen )
Aidin
Dodatkowo, jeśli później dodasz właściwość do foo, pojawi się ona automatycznie dla clonedFoo! np. foo.y = 9; console.log(clonedFoo.y)wydrukuje 9zamiast undefined. Jest bardzo prawdopodobne, że nie o to prosisz!
Aidin
@Aidin Jak więc zapewnić głęboką kopię?
Muhammad Ali
każde inne rozwiązanie w tym pytaniu, które polega na rekurencyjnym kopiowaniu przez wartość (np. stackoverflow.com/a/53025968 przez marckassay) zapewnia to, ponieważ nie ma odniesienia do obiektu źródłowego utrzymywanego w obiekcie docelowym.
Aidin
5

Możesz też mieć coś takiego:

class Entity {
    id: number;

    constructor(id: number) {
        this.id = id;
    }

    clone(): this {
        return new (this.constructor as typeof Entity)(this.id) as this;
    }
}

class Customer extends Entity {
    name: string;

    constructor(id: number, name: string) {
        super(id);
        this.name = name;
    }

    clone(): this {
        return new (this.constructor as typeof Customer)(this.id, this.name) as this;
    }
}

Po prostu upewnij się, że nadpisałeś clonemetodę we wszystkich Entitypodklasach, w przeciwnym razie otrzymasz częściowe klony.

Zwracany typ thiszawsze będzie zgodny z typem instancji.

Dekada księżyca
źródło
4

Dodaj "lodash.clonedeep": "^4.5.0"do swojego package.json. Następnie użyj w ten sposób:

import * as _ from 'lodash';

...

const copy = _.cloneDeep(original)
user2878850
źródło
3

Oto mój mash-up! A tutaj jest łącze StackBlitz do niego. Obecnie ogranicza się tylko do kopiowania prostych typów i typów obiektów, ale myślę, że można je łatwo zmodyfikować.

   let deepClone = <T>(source: T): { [k: string]: any } => {
      let results: { [k: string]: any } = {};
      for (let P in source) {
        if (typeof source[P] === 'object') {
          results[P] = deepClone(source[P]);
        } else {
          results[P] = source[P];
        }
      }
      return results;
    };
marckassay
źródło
1
O ile widzę, działa całkiem nieźle. Jednak typeof nulljest również obiektem, więc if (source[P] !== null && typeof source[P] === 'object')zamiast tego zapytanie powinno być . W przeciwnym razie twoje wartości null zostaną zamienione w pusty obiekt.
MortenMoulder
3

Jeśli pojawi się ten błąd:

TypeError: this.constructor(...) is not a function

To jest poprawny skrypt:

public clone(): any {
    var cloneObj = new (<any>this.constructor)(); // line fixed
    for (var attribut in this) {
        if (typeof this[attribut] === "object") {
            cloneObj[attribut] = this[attribut].clone();
        } else {
            cloneObj[attribut] = this[attribut];
        }
    }
    return cloneObj;
}
pablorsk
źródło
4
Jest poprawne cloneObj[attribut] = this.clone();? lub masz na myślicloneObj[attribut] = this[attribut].clone();
Serginho
2

Sam przeszedłem przez ten problem i na koniec napisałem małą bibliotekę cloneable-ts, która zapewnia klasę abstrakcyjną, która dodaje metodę clone do każdej klasy rozszerzającej ją. Klasa abstrakcyjna pożycza funkcję Deep Copy opisaną w zaakceptowanej odpowiedzi przez Fentona, zastępując ją jedynie copy = {};w copy = Object.create(originalObj)celu zachowania klasy oryginalnego obiektu. Oto przykład użycia klasy.

import {Cloneable, CloneableArgs} from 'cloneable-ts';

// Interface that will be used as named arguments to initialize and clone an object
interface PersonArgs {
    readonly name: string;
    readonly age: number;
}

// Cloneable abstract class initializes the object with super method and adds the clone method
// CloneableArgs interface ensures that all properties defined in the argument interface are defined in class
class Person extends Cloneable<TestArgs>  implements CloneableArgs<PersonArgs> {
    readonly name: string;
    readonly age: number;

    constructor(args: TestArgs) {
        super(args);
    }
}

const a = new Person({name: 'Alice', age: 28});
const b = a.clone({name: 'Bob'})
a.name // Alice
b.name // Bob
b.age // 28

Lub możesz po prostu użyć Cloneable.clonemetody pomocniczej:

import {Cloneable} from 'cloneable-ts';

interface Person {
    readonly name: string;
    readonly age: number;
}

const a: Person = {name: 'Alice', age: 28};
const b = Cloneable.clone(a, {name: 'Bob'})
a.name // Alice
b.name // Bob
b.age // 28    
Tim Osadchiy
źródło
1

Od czasu wydania TypeScript 3.7 obsługiwane są rekursywne aliasy typów, co pozwala nam zdefiniować funkcję bezpieczną dla typu deepCopy():

// DeepCopy type can be easily extended by other types,
// like Set & Map if the implementation supports them.
type DeepCopy<T> =
    T extends undefined | null | boolean | string | number ? T :
    T extends Function | Set<any> | Map<any, any> ? unknown :
    T extends ReadonlyArray<infer U> ? Array<DeepCopy<U>> :
    { [K in keyof T]: DeepCopy<T[K]> };

function deepCopy<T>(obj: T): DeepCopy<T> {
    // implementation doesn't matter, just use the simplest
    return JSON.parse(JSON.stringify(obj));
}

interface User {
    name: string,
    achievements: readonly string[],
    extras?: {
        city: string;
    }
}

type UncopiableUser = User & {
    delete: () => void
};

declare const user: User;
const userCopy: User = deepCopy(user); // no errors

declare const uncopiableUser: UncopiableUser;
const uncopiableUserCopy: UncopiableUser = deepCopy(uncopiableUser); // compile time error

Plac zabaw

Valeriy Katkov
źródło
0

Aby uzyskać prosty klon zawartości obiektu hole, po prostu określam i analizuję instancję:

let cloneObject = JSON.parse(JSON.stringify(objectToClone))

Podczas gdy zmieniam dane w drzewie objectToClone, nie ma zmiany w cloneObject. To było moje wymaganie.

Mam nadzieję, że to pomoże

Ferhatos
źródło
1
Może przegapić klucze z undefinedwartością. Zobacz mój komentarz na temat podobnej odpowiedzi powyżej: stackoverflow.com/questions/28150967/typescript-cloning-object/…
Aidin
0

Skończyło się na zrobieniu:

public clone(): any {
  const result = new (<any>this.constructor);

  // some deserialization code I hade in place already...
  // which deep copies all serialized properties of the
  // object graph
  // result.deserialize(this)

  // you could use any of the usggestions in the other answers to
  // copy over all the desired fields / properties

  return result;
}

Ponieważ:

var cloneObj = new (<any>this.constructor());

z @Fenton podał błędy uruchomieniowe.

Wersja maszynopisu: 2.4.2

Bernoulli IT
źródło
0

A może stary dobry jQuery ?! Oto głęboki klon:

var clone = $.extend(true, {}, sourceObject);
alehro
źródło
To pytanie nie zostało oznaczone jako JQuery ani nie wspomniano w nim o JQuery. Włączenie JQuery do projektu tylko po to, aby wykonać głębokie klonowanie, byłoby również ogromnym kosztem.
LewisM
To w porządku, ale w OP nie chodzi o to, jak klonować, chodzi o zidentyfikowanie problemu w dostarczonym przez niego kodzie, a ty odpowiedziałeś sposobem klonowania jQuery bez odpowiedzi na pytanie. To nie ja cię zlekceważyłem, ale myślę, że to może być powód, dla którego zostałeś zlekceważony.
LewisM
0

Podjęłam próbę stworzenia ogólnej usługi kopiowania / klonowania, która zachowuje typy dla zagnieżdżonych obiektów. Chciałbym otrzymać informację zwrotną, jeśli robię coś źle, ale wydaje się, że jak dotąd działa ...

import { Injectable } from '@angular/core';

@Injectable()
export class CopyService {

  public deepCopy<T>(objectToClone: T): T {
    // If it's a simple type or null, just return it.
    if (typeof objectToClone === 'string' ||
      typeof objectToClone === 'number' ||
      typeof objectToClone === 'undefined' ||
      typeof objectToClone === 'symbol' ||
      typeof objectToClone === 'function' ||
      typeof objectToClone === 'boolean' ||
      objectToClone === null
    ) {
      return objectToClone;
    }

    // Otherwise, check if it has a constructor we can use to properly instantiate it...
    let ctor = Object.getPrototypeOf(objectToClone).constructor;
    if (ctor) {
      let clone = new ctor();

      // Once we've instantiated the correct type, assign the child properties with deep copies of the values
      Object.keys(objectToClone).forEach(key => {
        if (Array.isArray(objectToClone[key]))
          clone[key] = objectToClone[key].map(item => this.deepCopy(item));
        else
          clone[key] = this.deepCopy(objectToClone[key]);
      });

      if (JSON.stringify(objectToClone) !== JSON.stringify(clone))
        console.warn('object cloned, but doesnt match exactly...\nobject: ' + JSON.stringify(objectToClone) + "\nclone: " + JSON.stringify(clone))

      // return our cloned object...
      return clone;
    }
    else {
      //not sure this will ever get hit, but figured I'd have a catch call.
      console.log('deep copy found something it didnt know: ' + JSON.stringify(objectToClone));
      return objectToClone;
    }
  }
}
patrickbadley
źródło
0

W typeScript testuję z angularem i działa OK

deepCopy(obj) {


        var copy;

        // Handle the 3 simple types, and null or undefined
        if (null == obj || "object" != typeof obj) return obj;

        // Handle Date
        if (obj instanceof Date) {
            copy = new Date();
            copy.setTime(obj.getTime());
            return copy;
        }

        // Handle Array
        if (obj instanceof Array) {
            copy = [];
            for (var i = 0, len = obj.length; i < len; i++) {
                copy[i] = this.deepCopy(obj[i]);
            }
            return copy;
        }

        // Handle Object
        if (obj instanceof Object) {
            copy = {};
            for (var attr in obj) {
                if (obj.hasOwnProperty(attr)) copy[attr] = this.deepCopy(obj[attr]);
            }
            return copy;
        }

        throw new Error("Unable to copy obj! Its type isn't supported.");
    }
maty jimenez
źródło
0

Do głębokiego klonowania obiektu, który może zawierać inne obiekty, tablice itd., Używam:

const clone = <T>(source: T): T => {
  if (source === null) return source

  if (source instanceof Date) return new Date(source.getTime()) as any

  if (source instanceof Array) return source.map((item: any) => clone<any>(item)) as any

  if (typeof source === 'object' && source !== {}) {
    const clonnedObj = { ...(source as { [key: string]: any }) } as { [key: string]: any }
    Object.keys(clonnedObj).forEach(prop => {
      clonnedObj[prop] = clone<any>(clonnedObj[prop])
    })

    return clonnedObj as T
  }

  return source
}

Posługiwać się:

const obj = {a: [1,2], b: 's', c: () => { return 'h'; }, d: null, e: {a:['x'] }}
const objClone = clone(obj)
RTW
źródło
0

Możesz użyć destrukcyjnego przypisania ze składnią rozprzestrzeniania :

var obj = {id = 1, name = 'product1'};
var clonedObject = {...obj};
SOUVIK SAHA
źródło
1
Chociaż ten kod może odpowiedzieć na pytanie, dostarczenie dodatkowego kontekstu dotyczącego tego, jak i / lub dlaczego rozwiązuje problem, poprawiłoby długoterminową wartość odpowiedzi.
leopal
-2

Jeśli masz już obiekt docelowy, więc nie chcesz tworzyć go od nowa (jak w przypadku aktualizacji tablicy), musisz skopiować właściwości.
Jeśli zrobiłeś to w ten sposób:

Object.keys(source).forEach((key) => {
    copy[key] = source[key]
})

Pochwała jest należna. (spójrz na nagłówek „wersja 2”)

LosManos
źródło
Funkcje? Tablice? Obiekty daty? Zachowanie typów? A co oczywiście z przedmiotami? Jeśli powyższa funkcja napotka którykolwiek z powyższych typów, głębokie klonowanie nie powiedzie się. Skopiujesz odniesienia do tych samych danych. Kiedy przejdą do edycji właściwości potomnych sklonowanego obiektu, ostatecznie edytują również oryginalny obiekt.
Pangamma