javascript - 함수 - 자바 스크립트에서 배열을 복제하는 가장 빠른 방법-슬라이스 대 'for'루프




자바스크립트 배열 (11)

배열 복제

필자는 배열을 복제하는 데 걸리는 시간을 테스트하는 매우 간단한 유틸리티 함수를 만들었습니다. 100 % 신뢰할 수있는 것은 아니지만 기존 어레이를 복제하는 데 걸리는 시간을 일괄 적으로 알려줄 수 있습니다.

function clone(fn) {
    const arr = [...Array(1000000)];
    console.time('timer');
    fn(arr);
    console.timeEnd('timer');
}

그리고 테스트 된 다른 접근법 :

1)   5.79ms -> clone(arr => Object.values(arr));
2)   7.23ms -> clone(arr => [].concat(arr));
3)   9.13ms -> clone(arr => arr.slice());
4)  24.04ms -> clone(arr => { const a = []; for (let val of arr) { a.push(val); } return a; });
5)  30.02ms -> clone(arr => [...arr]);
6)  39.72ms -> clone(arr => JSON.parse(JSON.stringify(arr)));
7)  99.80ms -> clone(arr => arr.map(i => i));
8) 259.29ms -> clone(arr => Object.assign([], arr));
9) Maximum call stack size exceeded -> clone(arr => Array.of(...arr));

자바 스크립트에서 배열을 복제하려면 다음 중 빠른 것을 사용하십시오.

슬라이스 방식

var dup_array = original_array.slice();

For 루프

for(var i = 0, len = original_array.length; i < len; ++i)
   dup_array[i] = original_array[i];

두 가지 방법 모두 얕은 복사 만 수행합니다. original_array에 객체에 대한 참조가 포함되어 있으면 객체가 복제되지 않지만 참조 만 복사되므로 두 배열 모두 동일한 객체에 대한 참조를 갖게됩니다. 그러나 이것은이 질문의 요점이 아닙니다.

속도에 대해서만 묻고 있습니다.


.slice ()는 2 차원 배열에서는 작동하지 않는다는 것을 기억하십시오. 다음과 같은 함수가 필요합니다.

function copy(array) {
  return array.map(function(arr) {
    return arr.slice();
  });
}

es6 방법은 어떨까요?

arr2 = [...arr1];

간단한 데모를 작성했습니다. http://jsbin.com/agugo3/edit

Internet Explorer 8의 결과는 156, 782 및 750이며,이 경우 slice 가 훨씬 빠름을 나타냅니다.


그것은 배열의 길이에 따라 다릅니다. 배열 길이가 <= 1,000,000보다 작 으면 sliceconcat 메서드가 거의 같은 시간이 걸립니다. 그러나 당신이 더 넓은 범위를 줄 때, concat 방법이 이깁니다.

예를 들어 다음 코드를 시도하십시오.

var original_array = [];
for(var i = 0; i < 10000000; i ++) {
    original_array.push( Math.floor(Math.random() * 1000000 + 1));
}

function a1() {
    var dup = [];
    var start = Date.now();
    dup = original_array.slice();
    var end = Date.now();
    console.log('slice method takes ' + (end - start) + ' ms');
}

function a2() {
    var dup = [];
    var start = Date.now();
    dup = original_array.concat([]);
    var end = Date.now();
    console.log('concat method takes ' + (end - start) + ' ms');
}

function a3() {
    var dup = [];
    var start = Date.now();
    for(var i = 0; i < original_array.length; i ++) {
        dup.push(original_array[i]);
    }
    var end = Date.now();
    console.log('for loop with push method takes ' + (end - start) + ' ms');
}

function a4() {
    var dup = [];
    var start = Date.now();
    for(var i = 0; i < original_array.length; i ++) {
        dup[i] = original_array[i];
    }
    var end = Date.now();
    console.log('for loop with = method takes ' + (end - start) + ' ms');
}

function a5() {
    var dup = new Array(original_array.length)
    var start = Date.now();
    for(var i = 0; i < original_array.length; i ++) {
        dup.push(original_array[i]);
    }
    var end = Date.now();
    console.log('for loop with = method and array constructor takes ' + (end - start) + ' ms');
}

a1();
a2();
a3();
a4();
a5();

original_array의 길이를 1,000,000으로 설정하면 slice 메소드와 concat 메소드가 거의 동일한 시간 (임의의 숫자에 따라 3-4ms)이 소요됩니다.

original_array의 길이를 10,000,000으로 설정하면 slice 메서드가 60ms 이상 걸릴 수 있고 concat 메서드는 20ms 이상 걸립니다.



깊은 복제를위한 가장 쉬운 방법 Array 또는 Object :

var dup_array = JSON.parse(JSON.stringify(original_array))

다음을보십시오 : link . 그것은 속도가 아니라 편안함에 관한 것입니다. 게다가 볼 수 있듯이 원시 타입 에서만 slice (0) 를 사용할 수 있습니다 .

배열에 대한 참조 복사본이 아닌 배열의 독립 복사본을 만들려면 배열 슬라이스 메서드를 사용할 수 있습니다.

예:

배열에 대한 참조 복사본이 아닌 배열의 독립 복사본을 만들려면 배열 슬라이스 메서드를 사용할 수 있습니다.

var oldArray = ["mip", "map", "mop"];
var newArray = oldArray.slice();

개체를 복사하거나 복제하려면 :

function cloneObject(source) {
    for (i in source) {
        if (typeof source[i] == 'source') {
            this[i] = new cloneObject(source[i]);
        }
        else{
            this[i] = source[i];
  }
    }
}

var obj1= {bla:'blabla',foo:'foofoo',etc:'etc'};
var obj2= new cloneObject(obj1);

출처 : link


훨씬 깨끗한 해결책이 있습니다.

var srcArray = [1, 2, 3];
var clonedArray = srcArray.length === 1 ? [srcArray[0]] : Array.apply(this, srcArray);

Array 생성자는 정확히 하나의 인수로 호출 될 때 다르게 동작하므로 길이 검사가 필요합니다.


Spread 연산자로 ECMAScript 2015 방식 :

기본 예 :

var copyOfOldArray = [...oldArray]
var twoArraysBecomeOne = [...firstArray, ..seccondArray]

브라우저 콘솔에서 다음을 시도하십시오.

var oldArray = [1, 2, 3]
var copyOfOldArray = [...oldArray]
console.log(oldArray)
console.log(copyOfOldArray)

var firstArray = [5, 6, 7]
var seccondArray = ["a", "b", "c"]
var twoArraysBecomOne = [...firstArray, ...seccondArray]
console.log(twoArraysBecomOne);

참고 문헌


var cloned_array = [].concat(target_array);




slice