[javascript] JavaScript에서 배열을 변경하면 배열 복사본에 영향을 미치는 이유는 무엇입니까?

다음 JavaScript를 작성했습니다.

var myArray = ['a', 'b', 'c'];
var copyOfMyArray = myArray;
copyOfMyArray.splice(0, 1);
alert(myArray); // alerts ['b','c']
alert(copyOfMyArray); // alerts ['b','c']

var myNumber = 5;
var copyOfMyNumber = myNumber;
copyOfMyNumber = copyOfMyNumber - 1;
alert(myNumber); // alerts 5
alert(copyOfMyNumber); // alerts 4        

이 코드는 변수를 선언하고 myArray배열 값으로 설정합니다. 그런 다음 두 번째 변수를 선언 copyOfMyArray하고로 설정합니다 myArray. 에서 작업을 수행 한 copyOfMyArray다음 myArray및 모두에 경고를 보냅니다 copyOfMyArray. 어떻게 든에서 작업을 수행하면 copyOfMyArray에서 동일한 작업이 수행되는 것처럼 보입니다 myArray.

그런 다음 코드는 숫자 값으로 동일한 작업을 수행합니다. 변수를 선언하고 myNumber이를 숫자 값으로 설정합니다. 그런 다음 두 번째 변수를 선언 copyOfMyNumber하고로 설정합니다 myNumber. 에서 작업을 수행 한 copyOfMyNumber다음 myNumber및 모두에 경고를 보냅니다 copyOfMyNumber. 여기에서 예상되는 동작을 얻습니다 . myNumber및에 대한 다른 값입니다 copyOfMyNumber.

배열을 변경하면 배열 사본의 값이 변경되는 것처럼 보이는 JavaScript에서 배열과 숫자의 차이점은 무엇입니까? 숫자를 변경해도 숫자 사본의 값은 변경되지 않습니까?

어떤 이유로 배열은 참조로 참조되고 숫자는 값으로 참조되지만 그 이유는 무엇입니까? 다른 개체에 대해 예상되는 동작을 어떻게 알 수 있습니까?



답변

JavaScript의 배열도 객체 이며 변수 는 객체 자체가 아닌 객체에 대한 참조 만 보유 합니다. 따라서 두 변수 모두 동일한 객체에 대한 참조를 갖습니다 .

숫자 예제와의 비교가 정확하지 않습니다. 에 새 값을 할당합니다 copyOfMyNumber. 새 값을 할당 copyOfMyArray해도 변경되지 않습니다 myArray.

slice [docs]를 사용하여 배열의 복사본을 만들 수 있습니다 .

var copyOfMyArray = myArray.slice(0);

그러나 이것은 얕은 복사본 만 반환합니다 . 즉, 배열 내부의 개체는 복제되지 않습니다.


답변

유일하게 가능한 대답과 정답은 실제로 어레이를 복사하지 않는다는 것입니다. 당신이 쓸 때

var copyOfArray = array;

동일한 배열에 대한 참조 를 다른 변수에 할당하고 있습니다. 즉, 둘 다 같은 물체를 가리키고 있습니다.


답변

그래서 여기있는 모든 사람들 이 이런 일이 일어나는지 설명하는 훌륭한 일을했습니다. 저는 그저 줄을 끊고 제가 어떻게이 문제를 해결할 수 있었 는지 알려 드리고 싶었습니다 . 아주 쉽게 :

thingArray = ['first_thing', 'second_thing', 'third_thing']
function removeFirstThingAndPreserveArray(){
  var copyOfThingArray = [...thingArray]
  copyOfThingArray.shift();
  return copyOfThingArray;
}

이것은 … spread 구문을 사용하고 있습니다.

스프레드 구문 소스

편집 : 이것의 이유 와 귀하의 질문에 대한 답변 :

배열을 변경하면 배열 사본의 값이 변경되는 것처럼 보이는 JavaScript에서 배열과 숫자의 차이점은 무엇입니까? 숫자를 변경해도 숫자 사본의 값은 변경되지 않습니까?

대답은 JavaScript에서 배열과 객체는 변경 가능 하고 문자열과 숫자 및 기타 기본 요소는 변경할 수 없다는 것입니다 . 다음과 같은 과제를 수행 할 때 :

var myArray = ['a', 'b', 'c'];
var copyOfMyArray = myArray;

copyOfMyArray는 실제 사본이 아니라 실제로 myArray에 대한 참조 일뿐입니다.

이 기사를 추천합니다. 불변 및 변경 가능한 데이터 구조는 무엇입니까? , 주제를 더 깊이 파헤칩니다.

MDN 용어 : 변경 가능


답변

개체 복제-

A는 loop / array.push비슷한 결과로 생산 array.slice(0)또는 array.clone(). 값은 모두 참조로 전달되지만 대부분의 원시 데이터 유형은 변경 불가능 하므로 후속 작업은 원하는 결과 인 ‘복제’를 생성합니다. 물론 원래 참조를 수정할 수있는 객체 및 배열에는 해당되지 않습니다 (변경 가능한 유형 임).

다음 예를 살펴보십시오.

const originalArray = [1, 'a', false, {foor: 'bar'}]
const newArray = [];

originalArray.forEach((v, i) => {
    newArray.push(originalArray[i]);
});

newArray[0] = newArray[0] + 1;
newArray[1] = 'b';
newArray[2] = true;
newArray[3] = Object.assign(newArray[3], {bar: 'foo'});

newArray 인덱스에서 실행되는 작업은 모두 원하는 결과를 생성합니다. 단, 최종 (객체)은 참조로 복사되기 때문에 originalArray [3]도 변경됩니다.

https://jsfiddle.net/7ajz2m6w/

참고 array.slice(0) and array.clone()이 같은 제한을 앓고 있습니다.

이를 해결하는 한 가지 방법은 푸시 시퀀스 중에 오브젝트를 효과적으로 복제하는 것입니다.

originalArray.forEach((v, i) => {
    const val = (typeof v === 'object') ? Object.assign({}, v) : v;
    newArray.push(val);
});

https://jsfiddle.net/e5hmnjp0/

건배


답변

JS에서 연산자 “=”는 포인터를 배열의 메모리 영역에 복사합니다. 배열을 다른 배열로 복사하려면 Clone 기능을 사용해야합니다.

정수의 경우 원시 유형이기 때문에 다릅니다.

에스.


답변

원시 데이터 유형 (문자열 및 숫자 IIRC)을 제외한 모든 것은 참조로 복사됩니다.


답변

사본이 없습니다.
동일한 배열을 보유하는 여러 변수가 있습니다.

마찬가지로 동일한 숫자를 가진 여러 변수가 있습니다.

를 쓸 때 copyOfMyNumber = ...변수에 새 숫자를 넣는 것입니다.
그것은 쓰기와 같습니다 copyOfMyArray = ....

당신이 쓸 때 copyOfMyArray.splice, 당신은하고 원래의 배열을 수정 .
숫자는 변경할 수없고 수정할 수 없기 때문에 불가능합니다.