21

The simple code below produces RangeError: Maximum call stack size exceeded

const arr = []
for (let i = 0; i < 135000; i++) {
    arr.push(i)
}
const arr2 = []
// something else here that changes arr2
arr2.push(...arr)

1) Why does this happen? (I am simply adding element to an array, why does it increase stack size ?)

2) How to fix this error ? (My goal is to create a shallow copy of arr into arr2)

2

3 Answers 3

15

The spread operator there pushes all elements in the original array into the stack, just like .apply:

const arr = [];

for (let i = 0; i < 10; i++) {
  arr.push(i);
}

const arr2 = [];

// Something else here that changes arr2:
arr2.push(0, 0, 0, 0, 0, 0, 0, 0, 0, 0);

Array.prototype.push.apply(arr2, arr);

console.log(arr2.join(', '));

So the amount of data you can handle in both cases is limited by the stack size:

const arr = [];

for (let i = 0; i < 135000; i++) {
  arr.push(i);
}

const arr2 = [];

// Something else here that changes arr2:
arr2.push(0, 0, 0, 0, 0, 0, 0, 0, 0, 0);

Array.prototype.push.apply(arr2, arr);

console.log(arr.length, arr2.length);

You could do this instead:

const arr = [];

for (let i = 0; i < 135000; i++) {
  arr.push(i);
}

let arr2 = [];

// Something else here that changes arr2:
arr2.push(0, 0, 0, 0, 0, 0, 0, 0, 0, 0);

arr2 = [...arr2, ...arr];

console.log(arr.length, arr2.length);

Sign up to request clarification or add additional context in comments.

2 Comments

Will this not recreate the entire arr2 array before adding the extra values? It'd be a problem for very large array.
Yes, the array is re-created.
5

When you use spread operator all items of the source array are stored in the stack as arguments list, so having a large number of items (~ > 100K) will cause the this stack size exceed.

The most simple work-around is to manually push all items one by one.

You can have a helper/utility function like this:

function largePush(src, dest){
    const len = src.length
    for(let i = 0; i < len; i++){
        dest.push(src[i])
    }
}

and use it like this:

const arr = []
for (let i = 0; i < 135000; i++) {
    arr.push(i)
}
const arr2 = []
largePush(arr, arr2)

Comments

-2

//I hope this will help you to make shallow copy of arr into arr2

let arr = []
for (let i = 0; i < 135000; i++) {
    arr.push(i)
}
let arr2 = []
// something else here that changes arr2
arr2=arr

console.log(arr2[0],arr[0]);
//Both 0,0
arr[0]=100

console.log(arr[0],arr2[0])

//Both 100,100

1 Comment

You are not making any copy of the original array, you are just aliasing it in another variable

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.