값별 배열 복사
JavaScript의 배열을 다른 배열에 복사할 경우:
var arr1 = ['a','b','c'];
var arr2 = arr1;
arr2.push('d'); //Now, arr1 = ['a','b','c','d']
가 깨달은 것은, 는것 i i i i i i i i 。arr2
.arr1
된 어레이를 얻는 어레이를 복사하여 2개의 독립된 어레이를 얻는 방법은 무엇입니까?
사용방법:
let oldArray = [1, 2, 3, 4, 5];
let newArray = oldArray.slice();
console.log({newArray});
기본적으로 이 작업은 어레이를 복제하고 새 어레이에 대한 참조를 반환합니다.
또, 다음의 점에 주의해 주세요.
참조, 문자열 및 숫자(실제 개체는 아님)의 경우 개체 참조를 새 배열에 복사합니다.원래 어레이와 새 어레이 모두 동일한 개체를 참조합니다.참조된 개체가 변경되면 변경 내용이 새 배열과 원래 배열 모두에 표시됩니다.
문자열이나 숫자와 같은 원시 요소는 불변하기 때문에 문자열이나 숫자를 변경할 수 없습니다.
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 () {}
이러한 요소로부터 3종류의 어레이를 작성할 수 있습니다.
// 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가지 어레이 유형에 따라 달라집니다.
어레이내의 요소의 타입에 근거해, 다양한 기술을 사용해 딥 카피를 실시할 수 있습니다.
딥 카피 기술
벤치마크
https://www.measurethat.net/Benchmarks/Show/17502/0/deep-copy-comparison
리럴type ( type 1 )
[ ...myArray ]
,myArray.splice(0)
,myArray.slice()
, , , , 입니다.myArray.concat()
할 수 있는 것은 값(리터럴,을 딥 입니다.여기서, 「」는, 「」(」, 「수」)입니다.slice()
하며 크롬을 확산시킵니다....
파이어폭스에서 최고의 성능을 발휘합니다.(type1)은 (type2)를 말합니다.
JSON.parse(JSON.stringify(myArray))
기술을 사용하여 리터럴 값(문자열, 숫자, 문자열) 및 리터럴 구조(배열, 객체)를 자세히 복사할 수 있지만 프로토타입 개체는 복사할 수 없습니다.모든 어레이(type1, type2, type3)
function copy(aObject) {
// Prevent undefined objects
// if (!aObject) return aObject;
let bObject = Array.isArray(aObject) ? [] : {};
let value;
for (const key in aObject) {
// Prevent self-references to parent object
// if (Object.is(aObject[key], aObject)) continue;
value = aObject[key];
bObject[key] = (typeof value === "object") ? copy(value) : value;
}
return bObject;
}
그래서 질문에 대답하자면...
질문.
var arr1 = ['a','b','c'];
var arr2 = arr1;
ar2는 새로운 독립 배열이 아닌 ar1과 같은 배열이라는 것을 알게 되었습니다.어레이를 복사하여 2개의 독립된 어레이를 얻는 방법은 무엇입니까?
정답.
★★★★★★★★★★★★★★★★★★arr1
값 문자열)의서는, 「」( 「」, 「」, 「」)의 임의의 딥 카피 방법을 할 수 .여기서 「」, 「」, 「」, 「」, 「」, 「」, 「」, 「」, 「」, 「」, 「」, 「」, 「」, 「」, 「」, 「」의 어느 쪽이든, 「」는 「」의 어느 쪽인가에 기재되어 있습니다.slice()
...
최고의 성능을 발휘합니다.
arr2 = arr1.slice();
arr2 = [...arr1];
arr2 = arr1.splice(0);
arr2 = arr1.concat();
arr2 = JSON.parse(JSON.stringify(arr1));
arr2 = copy(arr1); // Custom function needed, and provided above
arr2 = _.cloneDeep(arr1); // Lo-dash.js needed
arr2 = jQuery.extend(true, [], arr1); // jQuery.js needed
스프레드를 할 수 ....
어레이를 카피합니다.
const itemsCopy = [...items];
또한 기존 어레이가 포함된 새 어레이를 생성하는 경우에도 다음을 수행합니다.
var parts = ['shoulders', 'knees'];
var lyrics = ['head', ...parts, 'and', 'toes'];
어레이 확산은 모든 주요 브라우저에서 지원되지만 오래된 지원이 필요한 경우 스크립트 또는 바벨을 사용하여 ES5로 컴파일합니다.
jQuery가 필요 없습니다...작업 예시
var arr2 = arr1.slice()
하면 됩니다.0
이치노
기본 유형(문자열, 숫자 등)에 대해 예상대로 작동하고 참조 유형에 대해 예상되는 동작을 설명하는 것이 중요합니다.
타입의 는, 「」, 「」라고 합니다.Object
어레이는 복사되지만 양쪽 어레이에 동일한 참조가 포함됩니다.Object
s. 따라서 이 경우 어레이가 실제로 복사되어도 참조에 의해 복사되는 것처럼 보입니다.
여러 가지 방법을 시도해 본 결과, 다음과 같이 되었습니다.
var newArray = JSON.parse(JSON.stringify(orgArray));
이렇게 하면 첫 번째 복사본과 관련이 없는 새로운 딥 복사본이 생성됩니다(천박한 복사본이 아님).
또, 이벤트나 함수를 클로닝 하는 것은 아니고, 1행으로 실행할 수 있어 어떠한 오브젝트(어레이, 문자열, 숫자, 오브젝트 등)에도 사용할 수 있는 것이 장점입니다.
의 대체 방법은 두 가지 방법으로 사용할 수 있습니다.다음 중 첫 번째 항목은 의도된 동작이 매우 명확하기 때문에 더 읽기 쉬울 수 있습니다.
var array2 = [].concat(array1);
두 번째 방법은 다음과 같습니다.
var array2 = array1.concat();
Cohen은 (댓글에서) 후자의 방법이 더 나은 성과를 가지고 있다고 지적했습니다.
은, 「 」의 「 」입니다.concat
method는 오브젝트 내의 요소로 구성된 새로운 배열을 만듭니다.이 배열을 호출한 후 인수로서 전달되는 배열의 요소를 사용합니다.따라서 인수가 전달되지 않으면 어레이만 복사됩니다.
.array1
undefined
할 수
var array2 = [].concat(array1 || []);
또는 두 번째 방법의 경우:
var array2 = (array1 || []).concat();
은 '아까', '아까', '아까', '아까', '아까', '아까', 이렇게 할 수도 있다'에서도 할 수 요.slice
var array2 = (array1 || []).slice();
.
중요한!
이 답변의 대부분은 특정 경우에 유효합니다.
깊이 있는 물건이나 소품(ES6)에 관심이 없는 경우:
let clonedArray = [...array]
그러나 딥 클론을 수행하려면 대신 다음을 사용하십시오.
let cloneArray = JSON.parse(JSON.stringify(array))
*
* stringify를 사용하는 동안에는 보존(크기 조정)되지 않으며, 사용하지 않으면 결과를 얻을 수 있습니다.
lodash 사용자의 경우:
let clonedArray = _.clone(array)
문서화
그리고.
let clonedArray = _.cloneDeep(array)
문서화
저는 개인적으로 Array.from이 더 읽기 쉬운 솔루션이라고 생각합니다.참고로 브라우저 지원에 주의해 주세요.
// clone
let x = [1, 2, 3];
let y = Array.from(x);
console.log({y});
// deep clone
let clone = arr => Array.from(arr, item => Array.isArray(item) ? clone(item) : item);
x = [1, [], [[]]];
y = clone(x);
console.log({y});
위의 메서드 중 일부는 숫자나 문자열과 같은 단순한 데이터 유형으로 작업할 때 잘 작동하지만 배열에 다른 개체가 포함되어 있으면 이러한 메서드가 실패합니다.어레이 간에 개체를 전달하려고 하면 개체가 아닌 참조로 전달됩니다.
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()
그건 작동할 것이다.
ES2015부터
var arr2 = [...arr1];
ECMAScript 6 환경에 있는 경우 스프레드 연산자를 사용하여 다음과 같이 수행할 수 있습니다.
var arr1 = ['a','b','c'];
var arr2 = [...arr1]; //copy arr1
arr2.push('d');
console.log(arr1)
console.log(arr2)
<script src="http://www.wzvang.com/snippet/ignore_this_file.js"></script>
프리미티브 값은 항상 해당 값으로 전달됩니다(복사).그러나 복합값은 참조에 의해 전달됩니다.
그럼 이걸 어떻게 복사하죠?
let arr = [1,2,3,4,5];
ES6에서 어레이 복사
let arrCopy = [...arr];
ES5에서의 n 어레이 복사
let arrCopy = arr.slice();
let arrCopy = [].concat(arr);
let arrCopy = arr'이 값으로 전달되지 않는 이유는 무엇입니까?
개체/배열과 같은 복합값에서 변수 하나를 다른 변수에게 전달하면 동작이 달라집니다.코판드 값에 대한 asign 연산자를 사용하여 객체에 참조를 전달합니다.따라서 arr 요소를 제거/추가할 때 두 어레이의 값이 모두 변경됩니다.
예외:
arrCopy[1] = 'adding new value this way will unreference';
변수에 새 값을 할당하면 참조 자체가 변경되고 원래 개체/배열에는 영향을 주지 않습니다.
어레이 솔루션에 추가.slice(); 다차원 배열이 있는 경우 하위 문자열은 참조에 의해 복사된다는 점에 유의하십시오.각 서브 어레이를 개별적으로 루프 및 슬라이스()할 수 있습니다.
var arr = [[1,1,1],[2,2,2],[3,3,3]];
var arr2 = arr.slice();
arr2[0][1] = 55;
console.log(arr2[0][1]);
console.log(arr[0][1]);
function arrCpy(arrSrc, arrDis){
for(elm in arrSrc){
arrDis.push(arrSrc[elm].slice());
}
}
var arr3=[];
arrCpy(arr,arr3);
arr3[1][1] = 77;
console.log(arr3[1][1]);
console.log(arr[1][1]);
오브젝트 배열에 동일한 것이 할당되어 참조에 의해 복사되므로 수동으로 복사해야 합니다.
let a = [1,2,3];
이제 다음 중 하나를 수행하여 어레이의 복사본을 만들 수 있습니다.
let b = Array.from(a);
또는
let b = [...a];
또는
let b = new Array(...a);
또는
let b = a.slice();
또는
let b = a.map(e => e);
자, 만약 내가 a를
a.push(5);
그러면 a는 [1,2,3,5]이지만 b는 참조가 다르기 때문에 [1,2,3]이다.
하지만 위의 모든 방법에서 Array.from 주로 어레이를 복사하는 것이 좋습니다.
저는 개인적으로 다음과 같은 방법을 선호합니다.
JSON.parse(JSON.stringify( originalObject ));
정답이 많을 때 이 질문에 대한 베스트 프랙티스를 사용해야 합니다.
어레이를 카피하려면 , 어레이 스프레드를 사용하는 것을 추천합니다.
var arr1 = ['a','b','c'];
var arr2 = […arr1];
Javascript 어레이와 오브젝트는 참조에 의한 것이지만, 나중에 원래 어레이를 변경하지 않고 어레이를 복사할 수 있는 방법은 무엇입니까?
이를 위한 몇 가지 방법은 다음과 같습니다.
코드에 다음과 같은 배열이 있다고 가정해 보십시오.
var arr = [1, 2, 3, 4, 5];
1) 함수 내의 어레이를 루프하여 다음과 같이 새 어레이를 반환합니다.
function newArr(arr) {
var i=0, res = [];
while(i<arr.length){
res.push(arr[i]);
i++;
}
return res;
}
2) 슬라이스 방식을 사용하면 어레이의 일부를 슬라이스할 수 있습니다.슬라이스에서는 어레이의 시작과 끝을 지정하지 않으면 어레이 전체를 슬라이스하고 기본적으로 어레이의 완전한 복사본을 만들 수 있습니다.이렇게 쉽게 말할 수 있습니다.
var arr2 = arr.slice(); // make a copy of the original array
3) 또한 2개의 어레이를 Marge하기 위한 연락방법입니다.단, 어레이 중 하나를 지정하기만 하면 기본적으로 새로 연결된 어레이의 값 복사본을 만들 수 있습니다.
var arr2 = arr.concat();
4) 스트링화 및 해석방법도 권장하지 않지만 어레이와 오브젝트를 쉽게 복사할 수 있습니다.
var arr2 = JSON.parse(JSON.stringify(arr));
5) Array.from 메서드는 널리 지원되지 않습니다.사용하기 전에 다른 브라우저의 지원을 확인합니다.
const arr2 = Array.from(arr);
6) ECMA6 방식도 완전히 지원되지는 않지만, babelJs를 사용하면 다음과 같이 변환할 수 있습니다.
const arr2 = [...arr];
댄, 속임수 쓸 필요 없어이렇게 arr1을 복사하기만 하면 됩니다.
var arr1 = ['a','b','c'];
var arr2 = [];
var arr2 = new Array(arr1);
arr2.push('d'); // Now, arr2 = [['a','b','c'],'d']
console.log('arr1:');
console.log(arr1);
console.log('arr2:');
console.log(arr2);
// Following did the trick:
var arr3 = [...arr1];
arr3.push('d'); // Now, arr3 = ['a','b','c','d'];
console.log('arr3:');
console.log(arr3);
, 이제arr1
★★★★★★★★★★★★★★★★★」arr2
는 다른 스택에 저장되어 있는2개의 배열 변수입니다.jsfiddle에서 이것 좀 봐.
특히 어레이가 그대로 유지되도록 해야 했기 때문에 다음과 같은 작업을 수행할 수 있었습니다.
// Empty array
arr1.length = 0;
// Add items from source array to target array
for (var i = 0; i < arr2.length; i++) {
arr1.push(arr2[i]);
}
다차원 배열/개체 복사 만들기:
function deepCopy(obj) {
if (Object.prototype.toString.call(obj) === '[object Array]') {
var out = [], i = 0, len = obj.length;
for ( ; i < len; i++ ) {
out[i] = arguments.callee(obj[i]);
}
return out;
}
if (typeof obj === 'object') {
var out = {}, i;
for ( i in obj ) {
out[i] = arguments.callee(obj[i]);
}
return out;
}
return obj;
}
James Padolsey가 이 기능을 해줘서 고마워.
출처: 여기에서
배열에 int, char, string 등의 원시 데이터 유형의 요소가 포함되어 있는 경우 .slice() 또는 .map() 또는 spread 연산자(ES6 덕분에)와 같은 원래 배열의 복사본을 반환하는 메서드 중 하나를 사용할 수 있습니다.
new_array = old_array.slice()
또는
new_array = old_array.map((elem) => elem)
또는
const new_array = new Array(...old_array);
그러나 어레이에 오브젝트(또는 어레이)나 여러 개의 중첩된 오브젝트 등의 복잡한 요소가 포함되어 있는 경우 모든 요소의 복사를 최상위 레벨에서 마지막 레벨로 해야 합니다.그렇지 않은 경우 내부 오브젝트의 참조가 사용됩니다.즉, new_array의 object_elements 값을 변경하면 오래된 요소에 영향을 줍니다.array. 이 복사 방법은 old_array의 딥 복사라고 할 수 있습니다.
딥 카피에서는, 데이터 타입에 따라, 각 레벨의 원시 데이터 타입에 대해서 상기의 방법을 사용할 수도 있고, 큰 수고를 들이지 않고 딥 카피를 작성하기 위해서 코스트가 드는 방법(아래의 방법)을 사용할 수도 있습니다.
var new_array = JSON.parse(JSON.stringify(old_array));
그 밖에도 필요에 따라 사용할 수 있는 방법이 많이 있습니다.값별로 어레이를 다른 어레이에 복사하려고 하면 어떤 일이 일어나는지 대략적으로 설명하기 위해 일부만 언급했습니다.
개체 또는 배열의 새 복사본을 만들려면 개체 속성 또는 배열 요소를 명시적으로 복사해야 합니다. 예를 들어 다음과 같습니다.
var arr1 = ['a','b','c'];
var arr2 = [];
for (var i=0; i < arr1.length; i++) {
arr2[i] = arr1[i];
}
Google에서 불변의 프리미티브 값 및 가변 객체 참조에 대한 자세한 정보를 검색할 수 있습니다.
ES6를 spread Operartor와 함께 사용하면 더 간단합니다.
arr2 = [...arr1];
한계가 있다.check docs 구문 확산 @ mozilla
연산자( 「 」 )를 를 카피하는 .=
는 복사본을 는 복사본을 만들지 않고 포인터/참조만 어레이에 복사합니다.예를 들어 다음과 같습니다.
const oldArr = [1,2,3];
const newArr = oldArr; // now oldArr points to the same place in memory
console.log(oldArr === newArr); // Points to the same place in memory thus is true
const copy = [1,2,3];
console.log(copy === newArr); // Doesn't point to the same place in memory and thus is false
많은 경우 데이터를 변환할 때 초기 데이터 구조(예: 어레이)를 그대로 유지해야 합니다.델은 어레이를 정확하게 복사하여 초기 어레이를 그대로 유지하면서 변환할 수 있도록 합니다.
어레이 복사 방법:
const oldArr = [1,2,3];
// Uses the spread operator to spread out old values into the new array literal
const newArr1 = [...oldArr];
// Slice with no arguments returns the newly copied Array
const newArr2 = oldArr.slice();
// Map applies the callback to every element in the array and returns a new array
const newArr3 = oldArr.map((el) => el);
// Concat is used to merge arrays and returns a new array. Concat with no args copies an array
const newArr4 = oldArr.concat();
// Object.assign can be used to transfer all the properties into a new array literal
const newArr5 = Object.assign([], oldArr);
// Creating via the Array constructor using the new keyword
const newArr6 = new Array(...oldArr);
// For loop
function clone(base) {
const newArray = [];
for(let i= 0; i < base.length; i++) {
newArray[i] = base[i];
}
return newArray;
}
const newArr7 = clone(oldArr);
console.log(newArr1, newArr2, newArr3, newArr4, newArr5, newArr6, newArr7);
배열 또는 객체가 중첩될 때는 주의하십시오.
배열이 중첩되면 값이 참조에 의해 복사됩니다.다음으로 문제가 발생할 수 있는 예를 제시하겠습니다.
let arr1 = [1,2,[1,2,3]]
let arr2 = [...arr1];
arr2[2][0] = 5; // we change arr2
console.log(arr1); // arr1 is also changed because the array inside arr1 was copied by reference
따라서 어레이 내에 복사할 객체 또는 어레이가 있는 경우에는 이러한 방법을 사용하지 마십시오.이러한 방법은 기본 배열에만 사용하십시오.
javascript를 합니다.JSON.parse
JSON.stringify
이렇게요.
let arr1 = [1,2,[1,2,3]]
let arr2 = JSON.parse(JSON.stringify(arr1)) ;
arr2[2][0] = 5;
console.log(arr1); // now I'm not modified because I'm a deep clone
복사 성능:
최적의 퍼포먼스를 위해 어떤 것을 선택해야 할까요?으로는 '자세히'가 .for
루프 하다를 사용하세요.for
CPU 부하가 높은 카피(대규모/대규모 어레이)를 실현합니다.
후 ★★★★★★★★★★★★★★★★★..slice()
메소드는 또한 괜찮은 성능을 가지고 있으며 프로그래머가 구현하기 쉽고 상세하지 않습니다.사용할 것을 권장합니다..slice()
CPU 부하가 높지 않은 어레이를 일상적으로 복사할 수 있습니다., 「 」, 「 」는 주세요.JSON.parse(JSON.stringify(arr))
(오버헤드 감소) 딥 클론이 필요하지 않고 성능이 문제가 되는 경우.
var arr2 = arr1.120(0);
이 방법은 심플한 어레이에 적합합니다.
개체의 배열과 같은 복합 배열이 있는 경우 다음과 같은 다른 솔루션을 사용해야 합니다.
const arr2 = JSON.parse(JSON.stringify(arr1));
예를 들어 각 셀의 객체에 다른 배열 필드가 있는 객체의 배열이 있습니다.이 상황에서 슬라이스 방식을 사용하면 참조에 의해 배열 필드가 복사됩니다. 즉, 이러한 필드 갱신은 동일한 요소 및 필드에 조직 배열에 영향을 미칩니다.
jQuery 딥 복사는 다음과 같이 작성할 수 있습니다.
var arr2 = $.extend(true, [], arr1);
ES6 확산 연산자를 사용하여 어레이를 복사할 수도 있습니다.
var arr=[2,3,4,5];
var copyArr=[...arr];
다음은 복사하는 몇 가지 방법입니다.
const array = [1,2,3,4];
const arrayCopy1 = Object.values(array);
const arrayCopy2 = Object.assign([], array);
const arrayCopy3 = array.map(i => i);
const arrayCopy4 = Array.of(...array );
오브젝트를 포함하는 ES6 어레이의 경우
cloneArray(arr) {
return arr.map(x => ({ ...x }));
}
간단한 예:
- 어레이의 요소가 기본 유형(문자열, 숫자 등)인 경우
var arr1 = ['a','b','c'];
// arr1 and arr2 are independent and primitive elements are stored in
// different places in the memory
var arr2 = arr1.slice();
arr2.push('d');
console.log(arr1); // [ 'a', 'b', 'c' ]
console.log(arr2); // [ 'a', 'b', 'c', 'd' ]
- 어레이의 요소가 객체 리터럴인 경우 다른 어레이({}, [])
var arr1 = [{ x: 'a', y: 'b'}, [1, 2], [3, 4]];
// arr1 and arr2 are independent and reference's/addresses are stored in different
// places in the memory. But those reference's/addresses points to some common place
// in the memory.
var arr2 = arr1.slice();
arr2.pop(); // OK - don't affect arr1 bcos only the address in the arr2 is
// deleted not the data pointed by that address
arr2[0].x = 'z'; // not OK - affect arr1 bcos changes made in the common area
// pointed by the addresses in both arr1 and arr2
arr2[1][0] = 9; // not OK - same above reason
console.log(arr1); // [ { x: 'z', y: 'b' }, [ 9, 2 ], [ 3, 4 ] ]
console.log(arr2); // [ { x: 'z', y: 'b' }, [ 9, 2 ] ]
- 솔루션 2: 요소별 딥 복사
var arr1 = [{ x: 'a', y: 'b'}, [1, 2], [3, 4]];
arr2 = JSON.parse(JSON.stringify(arr1));
arr2.pop(); // OK - don't affect arr1
arr2[0].x = 'z'; // OK - don't affect arr1
arr2[1][0] = 9; // OK - don't affect arr1
console.log(arr1); // [ { x: 'a', y: 'b' }, [ 1, 2 ], [ 3, 4 ] ]
console.log(arr2); // [ { x: 'z', y: 'b' }, [ 9, 2 ] ]
언급URL : https://stackoverflow.com/questions/7486085/copy-array-by-value
'programing' 카테고리의 다른 글
MySQL - 열의 문자 바꾸기 (0) | 2023.01.05 |
---|---|
Javascript 객체의 첫 번째 속성에 액세스하는 방법은 무엇입니까? (0) | 2023.01.05 |
문자열에서 판다 데이터 프레임 생성 (0) | 2023.01.05 |
PHP YAML 파서 (0) | 2023.01.05 |
JavaScript에서 어제 날짜 계산 (0) | 2023.01.05 |