JavaScript의 경우 배열은 참조 유형입니다. 배열을 복사하려면 concat 및 슬라이스를 포함한 함수가 얕은 복사본이므로 잘 생각해야 합니다. 즉, 2차원 배열의 경우 concat을 사용하여 복사하면 2차원 배열은 여전히 참조입니다. 새 배열을 수정하면 이전 배열도 변경됩니다.
그때부터 그룹 딥카피에 도움이 되는 딥카피 기능을 작성하고 싶었습니다.
일반적으로 “="를 사용하여 할당을 수행할 수 있습니다. 그러나 배열, 객체, 함수 등과 같은 참조형 데이터의 경우 이 기호를 사용하기가 쉽지 않습니다.
1. 단순 배열 복사
1.1 단순 순회
가장 간단하고 기본적인 방법은 자연스러운 루프 처리입니다. 예:
JavaScript
function array_copy(arr) { var out = [], i, len; if (out[i] instanceof Array === false){ return arr; } for (i = 0, len = arr.length; i < len; i++) { if (out[i] instanceof Array){ out[i] = deepcopy(arr[i]); } else { out[i] = arr[i]; } }; return a; } //测试 var arr1 = [1, 2, 3, 4], arr2 = array_copy(arr1); console.log(arr1, arr2); arr2[2] = 10; console.log(arr1[2], arr2[2]); function array_copy(arr) { var out = [], i, len; if (out[i] instanceof Array === false){ return arr; } for (i = 0, len = arr.length; i < len; i++) { if (out[i] instanceof Array){ out[i] = deepcopy(arr[i]); } else { out[i] = arr[i]; } }; return a; } //测试 var arr1 = [1, 2, 3, 4], arr2 = array_copy(arr1); console.log(arr1, arr2); arr2[2] = 10; console.log(arr1[2], arr2[2]);
1.2 대체 카피 구현
면접 질문에 자주 등장하는 요령 구현 슬라이스 또는 contcat 방법을 사용합니다. 예:
JavaScript
var arr1 = [1, 2, 3, 4], arr2 = arr1.slice(0), arr3 = arr1.concat(); console.log(arr1, arr2, arr3); arr2[2] = 10; arr3[2] = 11; console.log(arr1[2], arr2[2], arr3[2]); var arr1 = [1, 2, 3, 4], arr2 = arr1.slice(0), arr3 = arr1.concat(); console.log(arr1, arr2, arr3); arr2[2] = 10; arr3[2] = 11; console.log(arr1[2], arr2[2], arr3[2]);
2. 배열의 전체 복사본
일반적인 1차원 배열과 값 비참조 유형의 경우 위의 방법을 사용하는 데 문제가 없습니다. 그렇지 않으면 더 번거로울 것입니다. 딥 카피는 배열 값이 다양한 참조 유형인 경우를 고려해야 합니다.
2.1 JSON 방식
JSON.stringify(array)를 사용한 다음 JSON.parse()를 사용합니다. 예:
JavaScript
var arr1 = [1, 2, [3, 4], {a: 5, b: 6}, 7], arr2 = JSON.parse(JSON.stringify(arr1)); console.log(arr1, arr2); arr2[1] = 10; arr2[3].a = 20; console.log(arr1[1], arr2[1]); console.log(arr1[3], arr2[3]); var arr1 = [1, 2, [3, 4], {a: 5, b: 6}, 7], arr2 = JSON.parse(JSON.stringify(arr1)); console.log(arr1, arr2); arr2[1] = 10; arr2[3].a = 20; console.log(arr1[1], arr2[1]); console.log(arr1[3], arr2[3]);
이 방법은 이전 브라우저와 호환성 문제가 있습니다. 실제로 호환성이 필요한 경우 다음과 같은 호환 파일을 도입할 수 있습니다.
https://github.com/douglascrockford/JSON-js/blob/master/json2.js
참고: 배열 값은 함수이며 위의 방법은 여전히 작동하지 않습니다.
2.2 딥 카피의 완전 구현
다차원 배열의 중첩과 배열 값이 객체인 상황을 고려하면 다음과 같은 프로토타입 확장이 가능하다(물론, 일반 함수 구현으로 작성할 수도 있습니다. 프로토타입 확장은 권장되지 않습니다.):
JavaScript
Object.prototype.clone = function () { var o = {}; for (var i in this) { o[i] = this[i]; } return o; }; Array.prototype.clone = function () { var arr = []; for (var i = 0; i < this.length; i++) if (typeof this[i] !== 'object') { arr.push(this[i]); } else { arr.push(this[i].clone()); } return arr; }; //测试1 Object var obj1 = { name: 'Rattz', age: 20, hello: function () { return "I'm " + name; } }; var obj2 = obj1.clone(); obj2.age++; console.log(obj1.age); //测试2 Array var fun = function(log) {console.log}, arr1 = [1, 2, [3, 4], {a: 5, b: 6}, fun], arr2 = arr1.clone(); console.log(arr1, arr2); arr2[2][1]= 'Mike'; arr2[3].a = 50; arr2[4] = 10; console.log(arr1, arr2); Object.prototype.clone = function () { var o = {}; for (var i in this) { o[i] = this[i]; } return o; Array.prototype.clone = function () { var arr = []; for (var i = 0; i < this.length; i++) if (typeof this[i] !== 'object') { arr.push(this[i]); } else { arr.push(this[i].clone()); } return arr; //测试1 Object var obj1 = { name: 'Rattz', age: 20, hello: function () { return "I'm " + name; } var obj2 = obj1.clone(); console.log(obj1.age); //测试2 Array var fun = function(log) {console.log}, arr1 = [1, 2, [3, 4], {a: 5, b: 6}, fun], arr2 = arr1.clone(); console.log(arr1, arr2); arr2[2][1]= 'Mike'; arr2[3].a = 50; arr2[4] = 10; console.log(arr1, arr2);
2.3 jQuery의 확장 메소드 사용
jQuery를 사용하는 경우 가장 쉬운 방법은 확장 플러그인 방법을 사용하는 것입니다. 예:
자바스크립트
var arr1 = [1, 2, [3, 4], {a: 5, b: 6}, 7], arr2 = $.extend(true, [], arr1); console.log(arr1, arr2); arr2[1] = 10; console.log(arr1, arr2); var arr1 = [1, 2, [3, 4], {a: 5, b: 6}, 7], arr2 = $.extend(true, [], arr1); console.log(arr1, arr2); arr2[1] = 10; console.log(arr1, arr2);