이것은 JavaScript 배열 사용에 대한 몇 가지 팁에 대한 간단한 기사입니다. 두 개의 JS 배열을 결합/병합하기 위해 다양한 방법을 사용하고 각 방법의 장점/단점에 대해 논의합니다.
먼저 다음 상황을 고려해 보겠습니다.
var a = [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]; var b = [ "foo", "bar", "baz", "bam", "bun", "fun" ];
당연히 가장 간단한 조합 결과는 다음과 같습니다.
[ 1, 2, 3, 4, 5, 6, 7, 8, 9, "foo", "bar", "baz", "bam" "bun", "fun" ]
concat(..)
이것이 가장 일반적인 접근 방식입니다.
var c = a.concat( b ); a; // [1,2,3,4,5,6,7,8,9] b; // ["foo","bar","baz","bam","bun","fun"] c; // [1,2,3,4,5,6,7,8,9,"foo","bar","baz","bam","bun","fun"]
보시다시피 C는 완전히 새로운 배열로, 두 배열 a와 b의 조합을 나타내고 A와 B는 그대로 둡니다. 간단하죠?
하지만 a에 10,000개의 요소가 있고 b에도 10,000개의 요소가 있으면 어떻게 될까요? C에는 20,000개의 요소가 있으므로 a와 b의 메모리 사용량은 두 배가 됩니다.
“문제없어!”라고 하셨습니다. 가비지 수집을 수행하고 A와 B를 null로 설정하면 문제가 해결됩니다!
a = b = null; // 'a'和'b'就被回收了
ㅎㅎ. 몇 개의 요소만 있는 작은 배열의 경우 이는 문제가 되지 않습니다. 그러나 대규모 어레이나 이 프로세스를 자주 반복해야 하는 메모리가 제한된 시스템의 경우 실제로 개선의 여지가 많습니다.
루프 삽입
좋습니다. 다음을 사용하여 한 배열의 내용을 다른 배열로 복사해 보겠습니다. Array#push(..)
// `b` onto `a` for (var i=0; i < b.length; i++) { a.push( b[i] ); } a; // [1,2,3,4,5,6,7,8,9,"foo","bar","baz","bam","bun","fun"] b = null;
이제 배열 a에는 배열의 내용 b.
메모리 사용량이 더 많은 것 같습니다.
그러나 배열 a가 상대적으로 작다면 어떨까요? 메모리 및 속도상의 이유로 b 앞에 작은 a를 배치하는 것이 좋습니다. 문제 없습니다. push(..)를 unshift(..)로 바꾸면 됩니다.
// `a` into `b`: for (var i=a.length-1; i >= 0; i--) { b.unshift( a[i] ); } b; // [1,2,3,4,5,6,7,8,9,"foo","bar","baz","bam","bun","fun"]
기능적 기술
그러나 for 루프는 실제로 보기 흉하고 유지 관리가 어렵습니다. 우리가 더 잘할 수 있을까요?
Array#reduce를 사용한 첫 번째 시도입니다.
// `b` onto `a`: a = b.reduce( function(coll,item){ coll.push( item ); return coll; }, a ); a; // [1,2,3,4,5,6,7,8,9,"foo","bar","baz","bam","bun","fun"] // or `a` into `b`: b = a.reduceRight( function(coll,item){ coll.unshift( item ); return coll; }, b ); b; // [1,2,3,4,5,6,7,8,9,"foo","bar","baz","bam","bun","fun"]
Array#reduce(..) 및 Array#reduceRight(..)는 훌륭하지만 조금 어색합니다. . ES6=>의 화살표 함수는 코드 양을 일부 줄여주지만 여전히 각 요소에 대해 한 번씩 호출해야 하는 함수가 필요하므로 완벽하지는 않습니다.
이거 어때요?
// `b` onto `a`: a.push.apply( a, b ); a; // [1,2,3,4,5,6,7,8,9,"foo","bar","baz","bam","bun","fun"] // or `a` into `b`: b.unshift.apply( b, a ); b; // [1,2,3,4,5,6,7,8,9,"foo","bar","baz","bam","bun","fun"]
이게 훨씬 낫죠? 특히 unshift(..) 메소드는 여기서 이전의 역정렬에 대해 걱정할 필요가 없기 때문에 더욱 그렇습니다. ES6의 스팬 연산은 더 아름다울 것입니다: a.push( ...b) 또는 b.unshift( ...a
배열의 최대 길이 제한
첫 번째 주요 문제는 , 메모리 사용량이 두 배로 늘어났습니다(물론 일시적으로만!). 추가된 콘텐츠는 기본적으로 함수 호출을 통해 요소를 스택에 복사합니다. 또한 다른 JS 엔진에는 복사된 데이터의 길이에 제한이 있습니다. > 따라서 배열에 백만 개의 요소가 있는 경우 push(...) 또는 unshift(...) 에 허용된 호출 스택의 한계를 확실히 초과하게 됩니다. 아쉽게도 수천 개의 요소로도 괜찮습니다. 하지만 합리적인 길이 제한을 초과하지 않도록 주의해야 합니다.
참고: push(...) 및 unshift(...)와 동일한 splice(...)를 시도해 볼 수 있습니다. ).
이 최대 길이 제한을 피할 수 있는 방법이 있습니다.
function combineInto(a,b) { var len = a.length; for (var i=0; i < len; i=i+5000) { b.unshift.apply( b, a.slice( i, i+5000 ) ); } }