developer tip

변수의 값을 다른 값으로 복사

copycodes 2020. 10. 15. 07:58
반응형

변수의 값을 다른 값으로 복사


값으로 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가 숫자와 문자열의 중첩되지 않은 배열 인 경우에만 올바르게 작동합니다.


The reason for this is simple. JavaScript uses refereces, so when you assign b = a you are assigning a reference to b thus when updating a you are also updating b

I found this on stackoverflow and will help prevent things like this in the future by just calling this method if you want to do a deep copy of an object.

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

newVariable = originalVariable.valueOf();

for objects you can use, b = Object.assign({},a);


I do not understand why the answers are so complex. In Javascript, primitives (strings, numbers, etc) are passed by value, and copied. Objects, including arrays, are passed by reference. In any case, assignment of a new value or object reference to 'a' will not change 'b'. But changing the contents of 'a' will change the contents of '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'

Paste any of the above lines (one at a time) into node or any browser javascript console. Then type any variable and the console will show it's value.


For strings or input values you could simply use this:

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

Most of the answers here are using built-in methods or using libraries/frameworks. This simple method should work fine:

function copy(x) {
    return JSON.parse( JSON.stringify(x) );
}

// Usage
var a = 'some';
var b = copy(a);
a += 'thing';

console.log(b); // "some"

var c = { x: 1 };
var d = copy(c);
c.x = 2;

console.log(d); // { x: 1 }

I solved it myself for the time being. The original value has only 2 sub-properties. I reformed a new object with the properties from a and then assigned it to b. Now my event handler updates only b, and my original a stays as it is.

var a = { key1: 'value1', key2: 'value2' },
    b = a;

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

    //WIN
    b = { key1: a.key1, key2: a.key2 };
});

This works fine. I have not changed a single line anywhere in my code except for the above, and it works just how I wanted it to. So, trust me, nothing else was updating a.


A solution for AngularJS:

$scope.targetObject = angular.copy($scope.sourceObject)

참고URL : https://stackoverflow.com/questions/18829099/copy-a-variables-value-into-another

반응형