clone - JavaScript Object assign - JavaScript 개체를 올바르게 복제하려면 어떻게합니까?

JavaScript shallow copy / javascript / javascript-objects

나는 객체 x 가 있습니다. 나는 개체로 복사 할 y 를 변경하도록, y 는 수정하지 않는 x . 기본 제공 JavaScript 개체에서 파생 된 개체를 복사하면 불필요한 속성이 추가로 발생한다는 것을 깨달았습니다. 내 자신의 리터럴로 구성된 객체 중 하나를 복사하기 때문에 이것은 문제가되지 않습니다.

Kamil Kiełczewski



Answer #1
function Circ() {
    this.me = this;
}

function Nested(y) {
    this.y = y;
}
var a = {
    x: 'a',
    circ: new Circ(),
    nested: new Nested('a')
};
var b = a;

b.x = 'b';
b.nested.y = 'b';

당신은 여기서 무슨 일이 일어 났는지 알고 있습니다. 그렇지 않다면이 위대한 질문에 착수하지 않을 것이기 때문입니다.

console.log(a, b);

a --> Object {
    x: "b",
    circ: Circ {
        me: Circ { ... }
    },
    nested: Nested {
        y: "b"
    }
}

b --> Object {
    x: "b",
    circ: Circ {
        me: Circ { ... }
    },
    nested: Nested {
        y: "b"
    }
}
var b = JSON.parse( JSON.stringify( a ) );

b.x = 'b';
b.nested.y = 'b';

허용되는 답변을 살펴 보겠습니다.

function cloneSO(obj) {
    // 3 가지 간단한 유형 및 null 또는 undefined 처리
    if (null == obj || "object" != typeof obj) return obj;

    // 날짜 처리
    if (obj instanceof Date) {
        var copy = new Date();
        copy.setTime(obj.getTime());
        return copy;
    }

    // 배열 처리
    if (obj instanceof Array) {
        var copy = [];
        for (var i = 0, len = obj.length; i < len; i++) {
            copy[i] = cloneSO(obj[i]);
        }
        return copy;
    }

    // 객체 처리
    if (obj instanceof Object) {
        var copy = {};
        for (var attr in obj) {
            if (obj.hasOwnProperty(attr)) copy[attr] = cloneSO(obj[attr]);
        }
        return copy;
    }

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

b.x = 'b';
b.nested.y = 'b';
var b = Object.create(a);

b.x = 'b';
b.nested.y = 'b';
console.log(a, b);

a --> Object {
    x: "a",
    circ: Circ {
        me: Circ { ... }
    },
    nested: Nested {
        y: "b"
    }
}

b --> Object {
    x: "b",
    circ: Circ {
        me: Circ { ... }
    },
    nested: Nested {
        y: "b"
    }
}
function F() {};
function clonePF(o) {
    F.prototype = o;
    return new F();
}

var b = clonePF(a);

b.x = 'b';
b.nested.y = 'b';
console.log(a, b);

a --> Object {
    x: "a",
    circ: Circ {
        me: Circ { ... }
    },
    nested: Nested {
        y: "b"
    }
}

b --> F {
    x: "b",
    circ: Circ {
        me: Circ { ... }
    },
    nested: Nested {
        y: "b"
    }
}

console.log(typeof a, typeof b);

a --> object
b --> object

console.log(a instanceof Object, b instanceof Object);

a --> true
b --> true

console.log(a instanceof F, b instanceof F);

a --> false
b --> true

주변을 파헤칠 때 비슷한 질문 ( Javascript에서 깊은 복사를 수행 할 때 속성이 "this"이기 때문에주기를 피하려면 어떻게해야합니까? )이 질문에 대해 더 나은 해결책을 찾았습니다 .

function cloneDR(o) {
    const gdcc = "__getDeepCircularCopy__";
    if (o !== Object(o)) {
        return o; // 원시 값
    }

    var set = gdcc in o,
        cache = o[gdcc],
        result;
    if (set && typeof cache == "function") {
        return cache();
    }
    // 그렇지 않으면
    o[gdcc] = function() { return result; }; // 덮어 쓰기
    if (o instanceof Array) {
        result = [];
        for (var i=0; i<o.length; i++) {
            result[i] = cloneDR(o[i]);
        }
    } else {
        result = {};
        for (var prop in o)
            if (prop != gdcc)
                result[prop] = cloneDR(o[prop]);
            else if (set)
                result[prop] = cloneDR(cache);
    }
    if (set) {
        o[gdcc] = cache; // 초기화
    } else {
        delete o[gdcc]; // 다시 설정 해제
    }
    return result;
}

var b = cloneDR(a);

b.x = 'b';
b.nested.y = 'b';

출력을 살펴 보겠습니다 ...

console.log(a, b);

a --> Object {
    x: "a",
    circ: Object {
        me: Object { ... }
    },
    nested: Object {
        y: "a"
    }
}

b --> Object {
    x: "b",
    circ: Object {
        me: Object { ... }
    },
    nested: Object {
        y: "b"
    }
}

console.log(typeof a, typeof b);

a --> object
b --> object

console.log(a instanceof Object, b instanceof Object);

a --> true
b --> true

console.log(a instanceof F, b instanceof F);

a --> false
b --> false

잎을 공유하는 나무의 구조는 복사되지 않고 두 개의 독립적 인 잎이됩니다.

        [Object]                     [Object]
         /    \                       /    \
        /      \                     /      \
      |/_      _\|                 |/_      _\|  
  [Object]    [Object]   ===>  [Object]    [Object]
       \        /                 |           |
        \      /                  |           |
        _\|  |/_                 \|/         \|/
        [Object]               [Object]    [Object]