[javascript] 변수의 값을 다른 값으로 복사

값으로 JSON 개체가있는 변수가 있습니다. 이 변수를 다른 변수에 직접 할당하여 동일한 값을 공유합니다. 작동 방식 :

var a = $('#some_hidden_var').val(),
    b = a;

이것은 효과가 있으며 둘 다 동일한 가치를 갖습니다. mousemove이벤트 핸들러를 사용하여 b내 앱 을 업데이트 합니다. 버튼을 클릭하면에 b저장된 값을 의미하는 원래 값 으로 되돌리고 싶습니다 a.

$('#revert').on('click', function(e){
    b = a;
});

그 후 동일한 mousemove이벤트 핸들러를 사용하면 a및을 모두 업데이트 하고 b이전에는 b예상 대로만 업데이트했습니다 .

나는이 문제에 대해 난처하다! 여기서 무엇이 잘못 되었습니까?



답변

=JavaScript 의 연산자가하는 일과하지 않는 일 을 이해하는 것이 중요합니다 .

=연산자는하지 않습니다 사본 데이터를.

=운영자는 새로운 생성 참조 받는 동일한 데이터.

원본 코드를 실행 한 후 :

var a = $('#some_hidden_var').val(),
    b = a;

a그리고 b두 개의 다른 이름 지금 같은 객체 .

이 개체의 내용에 대한 변경 사항은 a변수를 통해 참조하든 변수를 통해 참조하든 동일하게 표시됩니다 b. 그들은 같은 대상입니다.

따라서 나중에 다음 코드 b를 사용하여 원래 a개체 로 “복원”하려고 할 때 :

b = a;

코드는 실제로하지 않습니다 전혀 아무것도 때문에, a그리고 b정확히 같은 일이다. 코드는 작성한 것처럼 동일합니다.

b = b;

분명히 아무것도하지 않을 것입니다.

새 코드가 작동하는 이유는 무엇입니까?

b = { key1: a.key1, key2: a.key2 };

여기에서는 {...}개체 리터럴을 사용하여 새로운 개체를 만듭니다. 이 새 개체는 이전 개체와 동일하지 않습니다. 이제 b원하는 작업을 수행하는이 새 개체에 대한 참조로 설정 하고 있습니다.

임의의 객체를 처리하려면 Armand의 답변에 나열된 것과 같은 객체 복제 기능을 사용하거나 jQuery를 사용하기 때문에 $.extend()function을 사용하십시오 . 이 함수는 객체의 얕은 복사본 또는 깊은 복사본을 만듭니다. ( 이를 객체가 아닌 DOM 요소를 복사 하는 $().clone()방법 과 혼동하지 마십시오 .)

얕은 사본의 경우 :

b = $.extend( {}, a );

또는 딥 카피 :

b = $.extend( true, {}, a );

얕은 사본과 깊은 사본의 차이점은 무엇입니까? 단순 복사본은 개체 리터럴을 사용하여 새 개체를 만드는 코드와 유사합니다. 원래 개체와 동일한 속성에 대한 참조를 포함하는 새 최상위 개체를 만듭니다.

객체에 숫자 및 문자열과 같은 기본 유형 만 포함 된 경우 전체 복사 및 얕은 복사는 정확히 동일한 작업을 수행합니다. 그러나 개체가 그 안에 중첩 된 다른 객체 또는 배열에 포함되어있는 경우에 해당 얕은 복사가되지 않습니다 복사 하는 중첩 된 객체를, 그것은 단지 그들에 대한 참조를 만듭니다. 따라서 최상위 개체와 마찬가지로 중첩 된 개체에도 동일한 문제가 발생할 수 있습니다. 예를 들어 다음 개체가 주어지면 :

var obj = {
    w: 123,
    x: {
        y: 456,
        z: 789
    }
};

해당 객체의 얕은 복사를 수행하는 경우 x새 객체 의 속성은 x원본 과 동일한 객체입니다.

var copy = $.extend( {}, obj );
copy.w = 321;
copy.x.y = 654;

이제 개체는 다음과 같습니다.

// copy looks as expected
var copy = {
    w: 321,
    x: {
        y: 654,
        z: 789
    }
};

// But changing copy.x.y also changed obj.x.y!
var obj = {
    w: 123,  // changing copy.w didn't affect obj.w
    x: {
        y: 654,  // changing copy.x.y also changed obj.x.y
        z: 789
    }
};

딥 카피로 이것을 피할 수 있습니다. 전체 복사는 모든 중첩 된 객체와 배열 (그리고 Armand의 코드에서 Date)로 반복되어 최상위 객체의 사본을 만든 것과 동일한 방식으로 해당 객체의 사본을 만듭니다. 그래서 변화 copy.x.y에 영향을주지 것입니다 obj.x.y.

짧은 대답 : 확실하지 않은 경우 딥 카피를 원할 것입니다.


답변

JSON 작동 방식을 찾았지만 순환 참조를 확인하십시오.

var newInstance = JSON.parse(JSON.stringify(firstInstance));


답변

이 문제는 꽤 오랜 시간 동안 이미 해결되었지만 향후 참조를 위해 가능한 해결책은 다음과 같습니다.

b = a.slice(0);

주의하세요. 이것은 a가 숫자와 문자열의 중첩되지 않은 배열 인 경우에만 올바르게 작동합니다.


답변

newVariable = originalVariable.valueOf();

사용할 수있는 개체에 대해
b = Object.assign({},a);


답변

그 이유는 간단합니다. JavaScript는 b = a참조를 사용 b하므로 할당 할 때 참조를 할당 하므로 업데이트 a할 때도 업데이트됩니다.b

나는 이것을 stackoverflow 에서 찾았고 객체의 깊은 복사를 원할 경우이 메서드를 호출하여 앞으로 이와 같은 것을 방지하는 데 도움이 될 것입니다.

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

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

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

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

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


답변

나는 대답이 왜 그렇게 복잡한 지 이해하지 못한다. 자바 스크립트에서 프리미티브 (문자열, 숫자 등)는 값으로 전달되고 복사됩니다. 배열을 포함한 객체는 참조로 전달됩니다. 어쨌든 ‘a’에 대한 새 값 또는 개체 참조를 할당해도 ‘b’는 변경되지 않습니다. 그러나 ‘a’의 내용을 변경하면 ‘b’의 내용이 변경됩니다.

var a = 'a'; var b = a; a = 'c'; // b === 'a'

var a = {a:'a'}; var b = a; a = {c:'c'}; // b === {a:'a'} and a = {c:'c'}

var a = {a:'a'}; var b = a; a.a = 'c'; // b.a === 'c' and a.a === 'c'

위의 행 (한 번에 하나씩)을 노드 또는 브라우저 자바 스크립트 콘솔에 붙여 넣습니다. 그런 다음 변수를 입력하면 콘솔에 값이 표시됩니다.


답변

문자열 또는 입력 값의 경우 간단히 다음을 사용할 수 있습니다.

var a = $('#some_hidden_var').val(),
b = a.substr(0);