타이프 스크립트-복제 객체


187

I는 슈퍼 클래스가 부모 ( Entity많은 서브 클래스) ( Customer, Product, ProductCategory...)

Typescript에 다른 하위 객체가 포함 된 객체를 동적으로 복제하려고합니다.

예 : Customer다른 Product사람을 가진 사람ProductCategory

var cust:Customer  = new Customer ();

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

객체의 전체 트리를 복제하기 위해 함수를 만들었습니다. 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;
}

new이 자바 스크립트에 transpiled되어 다음과 같은 오류가 상승 :error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature.

스크립트가 작동하지만 변환 된 오류를 제거하고 싶습니다.

답변:


255

특정 문제 해결

형식 어설 션을 사용하여 컴파일러에 더 잘 알 수 있습니다.

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;
}

클로닝

때로는 완전히 역동적이지 않고 자신 만의 매핑을 작성하는 것이 좋습니다. 그러나 차이 효과를주는 몇 가지 "복제"트릭이 있습니다.

모든 후속 예제에 다음 코드를 사용합니다.

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'));

옵션 1 : 스프레드

속성 :
방법 : 아니요
딥 카피 : 아니요

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

옵션 2 : Object.assign

속성 :
방법 : 아니요
딥 카피 : 아니요

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

옵션 3 : Object.create

속성 : 상속 된
메서드 : 상속 된
깊은 복사 : 얕은 상속 (깊은 변경은 원본과 복제본 모두에 영향을 미침)

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

옵션 4 : 딥 카피 기능

속성 :
방법 : 아니요
딥 카피 :

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

닫기, transpile은 typescript 1.3에 대한 불만을 멈추었지만 Javascript에서는 한 번 오류가 발생합니다. Typescript 1.4.1은 놓지 않을 것입니다.
David Laberge

1
이것을 정확히 어떻게 사용하는지 명확하게 설명 하시겠습니까? 객체의 메소드로 포함시킨 다음 함수가 아니라는 오류가 발생했습니다.
megalucio

1
"오류 TypeError : this.constructor (...)는 생성자가 아닙니다"
michali

3
방금 그 고객으로부터 공개적인 예를 들었습니까?
블레어 코놀리

1
모든 답변에 주어진 솔루션 중 어떤 것이 클론의 OO 유형을 유지하는지 TL; DR이 될 수 있습니까 cloned instanceof MyClass === true?
Szczepan Hołyszewski

177

1. 스프레드 연산자 사용

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

스프레드 연산자는 obj1에서 모든 필드를 가져 와서 obj2에 펼칩니다. 결과적으로 새로운 참조 및 원래 필드와 동일한 필드를 가진 새 개체를 얻게됩니다.

얕은 사본이라는 것을 기억하십시오. 이는 객체가 중첩 된 경우 중첩 된 복합 매개 변수가 동일한 참조에 의해 새 객체에 존재 함을 의미합니다.

2. Object.assign ()

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

Object.assign은 실제 사본을 작성하지만 고유 한 특성 만 작성하므로 프로토 타입의 특성은 복사 된 오브젝트에 존재하지 않습니다. 얕은 사본이기도합니다.


3.Object.create ()

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

Object.create 실제 복제를 수행하지 않고 프로토 타입에서 객체를 생성합니다. 따라서 기본 유형 속성 지정은 참조로 수행되지 않으므로 오브젝트가 기본 유형 특성을 복제해야하는 경우이를 사용하십시오.

Object.create장점 은 프로토 타입에 선언 된 모든 함수를 새로 만든 객체에서 사용할 수 있다는 것입니다.


얕은 사본에 대한 몇 가지

얕은 복사는 이전 객체의 모든 필드를 새 객체에 넣지 만 원본 객체에 복합 유형 필드 (객체, 배열 등)가있는 경우 해당 필드는 동일한 참조를 가진 새 객체에 저장됩니다. 원래 객체에서 이러한 필드를 변경하면 새 객체에 반영됩니다.

함정처럼 보일 수도 있지만 복잡한 객체 전체를 복사해야하는 상황은 거의 없습니다. 얕은 사본은 대부분의 메모리를 재사용하므로 이는 깊은 사본에 비해 매우 저렴합니다.


딥 카피

스프레드 연산자는 딥 카피에 유용 할 수 있습니다.

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

위의 코드는 obj1의 깊은 복사본을 만들었습니다. 복합 필드 "복합"도 obj2에 복사되었습니다. 돌연변이 필드 "복합체"에는 사본이 반영되지 않습니다.


8
나는 그것이 완전히 옳다고 생각하지 않습니다. Object.create(obj1)새 객체를 만들고 obj1을 프로토 타입으로 할당합니다. obj1의 어떤 필드도 복사 또는 복제되지 않습니다. 따라서 obj2를 수정하지 않고 obj1의 변경 사항은 본질적으로 속성이 없으므로 표시됩니다. obj2를 먼저 수정하면 이름이있는 obj2의 필드가 계층 구조에 더 가깝기 때문에 사용자가 정의한 필드에 프로토 타입이 표시되지 않습니다.
Ken Rimple

3
또한 ES2015 및 typescript 개발자가 대신이 작업을 수행하여 첫 번째 매개 변수 (내 경우에는 빈 매개 변수)에서 개체를 만들고 두 번째 및 그 이후의 매개 변수에서 속성을 복사합니다. let b = Object.assign({}, a);
Ken Rimple

@KenRimple 당신은 100 % 맞습니다. 더 많은 정보를 추가했습니다.
Maciej Sikora


5
Object.assign은 깊은 개체에 대한 문제를 만듭니다. 예를 들어 {name : 'x', 값 : [ 'a', 'b', 'c']}입니다. Object.assign을 사용하여 복제 한 후 두 개체는 값 배열을 공유하므로 하나를 업데이트하면 다른 하나에 영향을줍니다. developer.mozilla.org/en/docs/Web/JavaScript/Reference/… ( '딥 클론에 대한 경고'섹션)를 참조하십시오 . 딥 클로닝을 위해서는 다른 대안을 사용해야합니다. 이는 할당되는 속성이 객체 일 때 Object.assign ()이 속성 참조를 복사하기 때문입니다.
Meir

48

이 시도:

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

매우 큰 객체를 사용하거나 객체에 직렬화 할 수없는 속성이있을 때까지 좋은 솔루션입니다.

형식 안전성을 유지하기 위해 복사하려는 클래스에서 복사 기능을 사용할 수 있습니다.

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

또는 정적 방식으로 :

static createCopy(objectToCopy: YourClassName): YourClassName{
    return (JSON.parse(JSON.stringify(objectToCopy)));
}

5
이것은 괜찮지 만 직렬화 / 구문 분석시 프로토 타입 정보와 json에서 지원되지 않는 모든 유형이 손실됩니다.
Stanislav E. Govorov

1
또한 이것은 위에서 제공된 deepCopy 함수와 비교할 때 효율성이 떨어지는 것 같습니다 .
Mojtaba

이 오류가 있습니다 : "(JSON.parse (JSON.stringify (objectToCopy)));"을 사용할 때 "원형 구조를 JSON으로 변환"
Cedric Arnould

98 %의 경우에만 작동합니다. undefined적어도 가치가있는 키가 누락 될 수 있습니다 . 경우 objectToCopy = { x : undefined};다음 코드를 실행 한 후 Object.keys(objectToCopy).length입니다 1, 동안은 Object.keys(copy).length입니다 0.
Aidin

33

TypeScript / JavaScript에는 얕은 복제를위한 자체 연산자가 있습니다.

let shallowClone = { ...original };

15

TypeScript 2.1에 도입 된 "Object Spread"를 사용하면 간단하게 복사본을 얻을 수 있습니다.

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

이 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


2
참고 : 이렇게하면 얕은 사본이 만들어집니다
Jimmy Kane

11

직렬화 가능 딥 클론의 경우 유형 정보는 다음과 같습니다.

export function clone<T>(a: T): T {
  return JSON.parse(JSON.stringify(a));
}

1
소품의 순서를 바꿀 수 있습니다. 일부 사람들에게는 경고 일뿐입니다. 또한 날짜를 올바르게 처리하지 못합니다.
Pangamma

이것은 소품의 순서를 바꿀 수 있습니다. 대신 npmjs.com/package/es6-json-stable-stringify 를 시도해보십시오JSON.stringify
Polv

@Polv, 누군가 객체의 키 순서에 의존하는 경우 키보다 큰 문제가 있다고 생각 clone합니다. :)
Aidin

이 솔루션은 undefined가치가있는 키를 놓칠 수 있습니다 . 위의 비슷한 답변에 대한 내 의견을 참조하십시오 : stackoverflow.com/questions/28150967/typescript-cloning-object/…
Aidin

7

내 생각은 :

Object.assign(...) 속성 만 복사하면 프로토 타입과 메서드가 손실됩니다.

Object.create(...) 속성을 복사하지 않고 프로토 타입을 만드는 것입니다.

나를 위해 일한 Object.create(...)것은 다음을 사용하여 속성을 사용 하고 속성을 복사 하는 프로토 타입을 만드는 것입니다 Object.assign(...).

따라서 객체의 foo경우 다음과 같이 복제하십시오.

Object.assign(Object.create(foo), foo)

여기에는 매우 미묘한 일이 있습니다. 실제로 (새 객체) foo의 프로토 타입 부모가되고 clonedFoo있습니다. 이것이 잘 들릴지 모르지만 누락 된 속성은 프로토 타입 체인에서 조회되므로 const a = { x: 8 }; const c = Object.assign(Object.create(a), a); delete c.x; console.log(c.x);8을 인쇄하지만 8은 인쇄해야합니다 undefined! (REPL 링크 : repl.it/repls/CompetitivePreemptiveKeygen )
Aidin

또한 나중에에 속성을 추가하면 !에 foo자동으로 표시됩니다 clonedFoo! 예를 들어 대신에 foo.y = 9; console.log(clonedFoo.y)인쇄됩니다 . 그것은 당신이 요구하는 것이 아닐 가능성이 큽니다! 9undefined
Aidin

@Aidin 그래서 깊은 사본을 보장하는 방법?
무하마드 알리

값으로 복사를 반복적으로 수행하는이 질문의 다른 솔루션 (예 : marckassay의 stackoverflow.com/a/53025968 )은 대상 객체에 유지되는 소스 객체에 대한 참조가 없기 때문에이를 보장합니다.
Aidin

5

다음과 같은 것을 가질 수도 있습니다.

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;
    }
}

clone모든 Entity서브 클래스 에서 메소드 를 대체하는지 확인하십시오. 그렇지 않으면 부분 복제가 발생합니다.

의 반환 유형 this은 항상 인스턴스 유형과 일치합니다.


4

에 추가 "lodash.clonedeep": "^4.5.0"하십시오 package.json. 그런 다음 다음과 같이 사용하십시오.

import * as _ from 'lodash';

...

const copy = _.cloneDeep(original)

3

여기 매시업입니다! 그리고 여기에 StackBlitz 링크 가 있습니다. 현재 단순한 유형과 객체 유형을 복사하는 것으로 제한되어 있지만 쉽게 수정할 수 있습니다.

   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;
    };

1
내가 볼 수있는 한 잘 작동합니다. 그러나 typeof null개체이기도하므로 if (source[P] !== null && typeof source[P] === 'object')대신 쿼리를 사용해야합니다 . 그렇지 않으면 null 값이 빈 객체로 바뀝니다.
MortenMoulder

3

이 오류가 발생하면 :

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

이것은 올바른 스크립트입니다.

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;
}

4
cloneObj[attribut] = this.clone();습니까? 또는 당신은cloneObj[attribut] = this[attribut].clone();
Serginho

2

이 문제를 직접 겪고 결국 추상 클래스를 제공하는 작은 라이브러리 cloneable-ts 를 작성하여 클래스를 확장하는 클래스에 클론 메소드를 추가합니다. 추상 클래스는 펜톤 만 교체하여 허용 대답에 설명 된 깊은 복사 기능 빌려 copy = {};copy = Object.create(originalObj)원본 객체의 클래스를 유지하기를. 다음은 클래스 사용 예입니다.

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

또는 Cloneable.clone도우미 메소드를 사용할 수도 있습니다 .

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    

1

TypeScript 3.7이 출시되었으므로 이제 재귀 적 유형 별칭 이 지원되며 유형 안전 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

운동장


0

구멍 객체의 내용을 간단히 복제하려면 간단히 인스턴스화하고 구문 분석하십시오.

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

objectToClone 트리에서 데이터를 변경하는 반면 cloneObject에는 변경이 없습니다. 그것은 나의 요구였다.

도움이되기를 바랍니다.


1
undefined가치가있는 키를 놓칠 수 있습니다. 위의 비슷한 답변에 대한 내 의견을 참조하십시오 : stackoverflow.com/questions/28150967/typescript-cloning-object/…
Aidin

0

나는 일을 끝내었다.

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;
}

때문에:

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

@Fenton에서 런타임 오류가 발생했습니다.

타이프 스크립트 버전 : 2.4.2


0

좋은 오래된 jQuery는 어떻습니까? 딥 클론은 다음과 같습니다.

var clone = $.extend(true, {}, sourceObject);

이 질문은 JQuery로 태그되지 않았으며 질문에서 JQuery로 언급되지 않았습니다. 또한 딥 클론을 수행하기 위해 프로젝트에 JQuery를 포함시키는 것은 엄청난 오버 헤드입니다.
LewisM

그것은 공평하지만 OP는 복제 방법에 관한 것이 아니라 그가 제공 한 코드에서 문제를 식별하는 것과 관련이 있으며 질문에 실제로 대답하지 않고 jQuery 복제 방법으로 응답했습니다. 난 당신을 억압 한 사람이 아니지만 나는 그것이 당신이 공감 된 이유 일 수 있다고 생각합니다.
LewisM

0

중첩 된 객체에 대한 유형을 유지하는 일반 복사 / 복제 서비스를 만드는 데 착수했습니다. 내가 잘못하고 있다면 피드백을 좋아할 것이지만 지금까지는 효과가있는 것 같습니다 ...

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;
    }
  }
}

0

typeScript에서 각도로 테스트하고 정상적으로 작동합니다.

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.");
    }

0

다른 객체, 배열 등을 포함 할 수있는 객체를 딥 클로닝하려면 다음을 사용하십시오.

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
}

사용하다:

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


-2

대상 객체가 이미 있으므로 배열을 업데이트하는 것처럼 새로 만들지 않으려면 속성을 복사해야합니다.
이 방법으로 수행 한 경우 :

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

찬양 예정입니다. (제목 "버전 2"를보십시오)


기능? 배열? 날짜 개체? 유형 보존? 물론 물체는 어떻습니까? 위의 함수가 위의 유형 중 하나를 만나면 딥 복제에 실패합니다. 동일한 데이터에 대한 참조를 복사했습니다. 복제 된 객체의 하위 속성을 편집하면 원래 객체도 편집됩니다.
Pangamma
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.