JavaScript의 배열을 다른 배열로 복사하는 경우 :
var arr1 = ['a','b','c'];
var arr2 = arr1;
arr2.push('d'); //Now, arr1 = ['a','b','c','d']
새로운 독립형 배열이 아닌와 arr2
동일한 배열 을 참조 한다는 것을 깨달았습니다 arr1
. 배열을 복사하여 두 개의 독립적 인 배열을 얻으려면 어떻게해야합니까?
답변
이것을 사용하십시오 :
var newArray = oldArray.slice();
기본적으로이 slice()
작업은 배열을 복제하고 새 배열에 대한 참조를 반환합니다.
또한 다음을 참고하십시오.
참조, 문자열 및 숫자 (실제 객체는 아님)의 경우 slice()
객체 참조를 새 배열에 복사합니다. 원래 배열과 새 배열은 모두 동일한 객체를 나타냅니다. 참조 된 객체가 변경되면 변경 사항이 새 배열과 원래 배열 모두에 표시됩니다.
문자열 및 숫자와 같은 기본 요소는 변경할 수 없으므로 문자열 또는 숫자를 변경할 수 없습니다.
답변
Javascript에서 딥 카피 기술은 배열의 요소에 따라 다릅니다. 거기서 시작하자.
세 가지 유형의 요소
요소는 리터럴 값, 리터럴 구조 또는 프로토 타입 일 수 있습니다.
// Literal values (type1)
const booleanLiteral = true;
const numberLiteral = 1;
const stringLiteral = 'true';
// Literal structures (type2)
const arrayLiteral = [];
const objectLiteral = {};
// Prototypes (type3)
const booleanPrototype = new Bool(true);
const numberPrototype = new Number(1);
const stringPrototype = new String('true');
const arrayPrototype = new Array();
const objectPrototype = new Object(); // or `new function () {}`
이 요소들로부터 우리는 세 가지 유형의 배열을 만들 수 있습니다.
// 1) Array of literal-values (boolean, number, string)
const type1 = [true, 1, "true"];
// 2) Array of literal-structures (array, object)
const type2 = [[], {}];
// 3) Array of prototype-objects (function)
const type3 = [function () {}, function () {}];
딥 카피 기술은 3 가지 어레이 유형에 따라 다릅니다.
배열의 요소 유형에 따라 다양한 기술을 사용하여 딥 카피 할 수 있습니다.
-
리터럴 값 (타입 1)의 배열 , , 및 기술은 단지 리터럴 값 (부울, 숫자 및 문자열) 깊은 복사 어레이에 사용될 수있다; Spread 연산자 가 최고의 성능을 발휘하는 곳 ( https://measurethat.net/Benchmarks/Show/4281/0/spread-array-performance-vs-slice-splice-concat ).
[...myArray]
myArray.splice(0)
myArray.slice()
myArray.concat()
[...myArray]
-
리터럴 값 (type1) 및 리터럴 구조 (type2)
의 배열 이JSON.parse(JSON.stringify(myArray))
기술을 사용하여 리터럴 값 (부울, 숫자, 문자열) 및 리터럴 구조 (배열, 객체)를 딥 카피 할 수 있지만 프로토 타입 객체는 사용할 수 없습니다. -
모든 배열 (type1, type2, type3)
jQuery$.extend(myArray)
기술을 사용하여 모든 배열 유형을 딥 카피 할 수 있습니다. Underscore 및 Lo-dash 와 같은 라이브러리는 jQuery 와 유사한 딥 카피 기능을 제공하지만$.extend()
성능은 떨어집니다. 놀랍게도 http://jsperf.com/js-deep-copy/15 기술$.extend()
보다 성능이 우수합니다 .
jQuery와 같은 타사 라이브러리를 사용하지 않는 개발자의 경우 다음과 같은 사용자 정의 기능을 사용할 수 있습니다. $ .extend보다 성능이 높고 모든 어레이를 딥 카피합니다.JSON.parse(JSON.stringify(myArray))
function copy(aObject) {
if (!aObject) {
return aObject;
}
let v;
let bObject = Array.isArray(aObject) ? [] : {};
for (const k in aObject) {
v = aObject[k];
bObject[k] = (typeof v === "object") ? copy(v) : v;
}
return bObject;
}
질문에 대답하려면 …
질문
var arr1 = ['a','b','c'];
var arr2 = arr1;
arr2는 새로운 독립형 배열이 아니라 arr1과 동일한 배열을 나타냅니다. 배열을 복사하여 두 개의 독립적 인 배열을 얻으려면 어떻게해야합니까?
대답
때문에 arr1
리터럴 값 (부울, 숫자 또는 문자열)의 배열, 당신은 확산 연산자는 위에서 설명한 어떤 깊은 복사 기술, 사용할 수있는 ...
가장 높은 성능을 가지고 있습니다.
// Highest performance for deep copying literal values
arr2 = [...arr1];
// Any of these techniques will deep copy literal values as well,
// but with lower performance.
arr2 = arr1.slice();
arr2 = arr1.splice(0);
arr2 = arr1.concat();
arr2 = JSON.parse(JSON.stringify(arr1));
arr2 = $.extend(true, [], arr1); // jQuery.js needed
arr2 = _.extend(arr1); // Underscore.js needed
arr2 = _.cloneDeep(arr1); // Lo-dash.js needed
arr2 = copy(arr1); // Custom-function needed - as provided above
답변
배열 스프레드 ...
를 사용하여 배열 을 복사 할 수 있습니다 .
const itemsCopy = [...items];
또한 기존 배열의 일부인 새 배열을 만들려면 다음을 수행하십시오.
var parts = ['shoulders', 'knees'];
var lyrics = ['head', ...parts, 'and', 'toes'];
어레이 스프레드는 이제 모든 주요 브라우저에서 지원 되지만 이전 지원이 필요한 경우 typescript 또는 babel을 사용하고 ES5로 컴파일하십시오.
답변
jQuery가 필요하지 않습니다 … 작업 예
var arr2 = arr1.slice()
그러면 배열이 시작 위치에서 배열 끝까지 복사 0
됩니다.
기본 유형 (문자열, 숫자 등)에 대해 예상대로 작동하고 참조 유형에 대해 예상되는 동작을 설명하는 것이 중요합니다 …
참조 유형의 배열이있는 경우 유형이라고 말하십시오 Object
. 배열 이 복사되지만 두 배열 모두에 대한 참조가 포함됩니다 Object
. 따라서이 경우 배열 이 실제로 복사 되더라도 배열 이 참조로 복사되는 것처럼 보입니다 .
답변
의 대안 slice
은 concat
2 가지 방법으로 사용할 수 있습니다. 의도 된 동작이 매우 명확하기 때문에 이들 중 첫 번째가 더 읽기 쉽습니다.
var array2 = [].concat(array1);
두 번째 방법은 다음과 같습니다.
var array2 = array1.concat();
Cohen (의견에서)은이 후자의 방법 이 더 나은 성능을 가지고 있다고 지적했다 .
이것이 작동하는 concat
방법은 메소드가 호출되는 객체의 요소와 인수로 전달 된 배열의 요소로 구성된 새 배열을 작성하는 것입니다. 따라서 인수가 전달되지 않으면 단순히 배열을 복사합니다.
Lee Penkman은 또한 의견에서 기회 array1
가 undefined
있으면 다음과 같이 빈 배열을 반환 할 수 있다고 지적 합니다.
var array2 = [].concat(array1 || []);
또는 두 번째 방법의 경우 :
var array2 = (array1 || []).concat();
다음과 slice
같이 할 수도 있습니다 var array2 = (array1 || []).slice();
.
답변
이것은 많은 접근법을 시도한 후에 내가 한 일입니다.
var newArray = JSON.parse(JSON.stringify(orgArray));
이렇게하면 첫 번째 사본과 관련이없는 새 사본이 생성됩니다 (얕은 사본이 아님).
또한 이것은 분명히 이벤트와 함수를 복제하지는 않지만 한 줄로 할 수있는 좋은 방법이며 모든 종류의 객체 (배열, 문자열, 숫자, 객체 …)에 사용할 수 있습니다
답변
언급 된 메소드 중 일부는 숫자 또는 문자열과 같은 간단한 데이터 유형으로 작업 할 때 잘 작동하지만 배열에 다른 오브젝트가 포함되어 있으면 이러한 메소드가 실패합니다. 한 배열에서 다른 배열로 객체를 전달하려고하면 객체가 아니라 참조로 전달됩니다.
JavaScript 파일에 다음 코드를 추가하십시오.
Object.prototype.clone = function() {
var newObj = (this instanceof Array) ? [] : {};
for (i in this) {
if (i == 'clone')
continue;
if (this[i] && typeof this[i] == "object") {
newObj[i] = this[i].clone();
}
else
newObj[i] = this[i]
} return newObj;
};
그리고 간단히 사용하십시오
var arr1 = ['val_1','val_2','val_3'];
var arr2 = arr1.clone()
작동합니다.