Search code examples
javascriptslicedestructuringshiftsplice

JS Array shift vs splice vs slice vs destructuring


Which approach to delete the first element of an array in js provides better performance?

Assume we have this array:

let fruits = ['Apple', 'Orange', 'Banana', 'Lemon'];

1. shift approach

let a = fruits.shift();

2. splice approach

let [b] = fruits.splice(0, 1);

3. slice approach

let c;
[c, fruits] = [...fruits.slice(0, 1), fruits.slice(1)]

4. Destructuring approach

let d;
[d, ...fruits] = fruits;

Please mention the reasons why one one these approaches is faster than another.

I did some tests in jsbench.me & perf.link but I ran the exact same tests multiple times and everytime I got 180 degrees opposite results.

I know this things are different from one environment and engine to another so I want to know which one is better in Chrome V8 engine.


Solution

  • In my experience, the .shift() method is the easiest to use. But if you want to know the exact code speed, I tested every method with performance.now().

    Mostly, the .shift() method is the fastest. You may ask why? Well, it doesn't redeclare any variables as the others are redefined. You only have on variable, which is automatically returned when calling the shift() method. Especially the last two examples are the slowest. They are redefining two variables, one is assigned two times (c, d). One time, just with let and the other time when declaring.

    Here's the code I used for testing, feel free to edit it.

        function speedTest(times) {
        let shiftAvg = 0;
        let spliceAvg = 0;
        let sliceAvg = 0;
        let destructuringAvg = 0;
        let t0, t1;
        let fruits = Array(10000).fill('test');
        for (var i = 0; i < times; i++) {
    
            t0 = performance.now();
        
            let a = fruits.shift();
        
            t1 = performance.now();
    
            shiftAvg += t1 - t0;
        
            resetFruits();
            
            t0 = performance.now();
        
            let [b] = fruits.splice(0, 1);
        
            t1 = performance.now();
            spliceAvg += t1 - t0;
        
            resetFruits();
            
            t0 = performance.now();
        
            let c;
            [c, fruits] = [...fruits.slice(0, 1), fruits.slice(1)];
        
            t1 = performance.now();
            sliceAvg += t1 - t0;
        
            resetFruits();
            
            t0 = performance.now();
        
            let d;
            [d, ...fruits] = fruits;
        
            t1 = performance.now();
            destructuringAvg += t1 - t0;
        
            resetFruits();
        }
        
        shiftAvg = shiftAvg / times;
        spliceAvg = spliceAvg / times;
        sliceAvg = sliceAvg / times;
        destructuringAvg = destructuringAvg / times;
    
        return [
            {"avg": destructuringAvg, "approach": 'destructuring'},
            {"avg": spliceAvg, "approach": 'splice'},
            {"avg": sliceAvg, "approach": 'slice'},
            {"avg": shiftAvg, "approach": 'shift'}
        ];
        
        function resetFruits() {
            fruits = Array(10000).fill('test');
        }
    }
    
    let result = speedTest(20000).sort((a, b) => (a.avg > b.avg) ? 1 : -1);
    
    result.map((item, index, self) => {
        if(index === 0) {
            console.log(index + 1, item.approach, item.avg, `fastest`);
        }
        else {
            console.log(index + 1, item.approach, item.avg, `${parseInt(item.avg / self[0].avg * 100 - 100)}% slower`);
        }
        
    });

    Also, not only the code execution speed is fast, but typing array.slice() is faster then for example typing out the whole destructuring code.

    I hope I was able to help you out :)