Search code examples
javascriptreactjsecmascript-6destructuring

Destructuring Variables Performance


Is there a performance difference, if any, between writing

const color = props.color;

vs

const { color } = props;

Also, do we gain or lose any performance if we destructure in the parameters signature? See example3

I assume example3 in this situation would be the best way to write the function?


Example functional react components:

const example1 = (props) => {
  const color = props.color;
  // I know I could also just write style={{ color: props.color }}
  // but for arguments sake lets say I want to write it like this.
  return <h1 style={{ color }}>Hello</h1>;
};

const example2 = (props) => {
  const { color } = props;
  return <h1 style={{ color }}>Hello</h1>;
};

const example3 = ({ color }) => {
  return <h1 style={{ color }}>Hello</h1>;
};

Solution

  • It's not necessarily true that a compiler/transpiler will always remove destructuring assignments as all evergreen browsers support destructuring natively as of 2020. As per, there is some evidence that as of at least 2018 the bytecode generated in V8 by a destructuring assignment is much more verbose than traditional function parameters:

    Function Parameters:

    function add(number1, number2){
      return number1 + number2;
    }
    const result = add(1,5);
    

    Output bytecode:

    [generating bytecode for function: add]
    Parameter count 3
    Frame size 0
       74 E> 0x2a2a0affd2a2 @    0 : 91                StackCheck 
       96 S> 0x2a2a0affd2a3 @    1 : 1d 02             Ldar a1
      111 E> 0x2a2a0affd2a5 @    3 : 2b 03 00          Add a0, [0]
      121 S> 0x2a2a0affd2a8 @    6 : 95                Return 
    Constant pool (size = 0)
    Handler Table (size = 16)
    

    Destructured Assignment:

    function add({number1, number2}){
      return number1 + number2;
    }
    const result = add({number1: 1, number2: 5});
    

    Output Bytecode:

    [generating bytecode for function: add]
    Parameter count 2
    Frame size 40
       74 E> 0x2c1d63b7d312 @    0 : 91                StackCheck 
             0x2c1d63b7d313 @    1 : 1f 02 fb          Mov a0, r0
             0x2c1d63b7d316 @    4 : 1d fb             Ldar r0
             0x2c1d63b7d318 @    6 : 89 06             JumpIfUndefined [6] (0x2c1d63b7d31e @ 12)
             0x2c1d63b7d31a @    8 : 1d fb             Ldar r0
             0x2c1d63b7d31c @   10 : 88 10             JumpIfNotNull [16] (0x2c1d63b7d32c @ 26)
             0x2c1d63b7d31e @   12 : 03 3f             LdaSmi [63]
             0x2c1d63b7d320 @   14 : 1e f8             Star r3
             0x2c1d63b7d322 @   16 : 09 00             LdaConstant [0]
             0x2c1d63b7d324 @   18 : 1e f7             Star r4
             0x2c1d63b7d326 @   20 : 53 e8 00 f8 02    CallRuntime [NewTypeError], r3-r4
       76 E> 0x2c1d63b7d32b @   25 : 93                Throw 
       76 S> 0x2c1d63b7d32c @   26 : 20 fb 00 02       LdaNamedProperty r0, [0], [2]
             0x2c1d63b7d330 @   30 : 1e fa             Star r1
       85 S> 0x2c1d63b7d332 @   32 : 20 fb 01 04       LdaNamedProperty r0, [1], [4]
             0x2c1d63b7d336 @   36 : 1e f9             Star r2
       98 S> 0x2c1d63b7d338 @   38 : 1d f9             Ldar r2
      113 E> 0x2c1d63b7d33a @   40 : 2b fa 06          Add r1, [6]
      123 S> 0x2c1d63b7d33d @   43 : 95                Return 
    Constant pool (size = 2)
    Handler Table (size = 16)
    

    The number of bytecode lines increased significantly from 4 in the case of function parameters to 19 in the case of the destructured assignment. In conclusion destructured assignments are less computationally efficient than traditional function parameters, as of 2018 in V8. In terms of memory space utilization the answer is a bit more complex and can be referenced here.

    This could be a premature optimization however in compute heavy code it may be advisable to consider not using destructuring assignments.