값으로 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);