34

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>;
};
Christian Bangert
  • 673
  • 1
  • 6
  • 16
  • 7
    Bearing in mind that you're using JSX, so your code is being transpiled before being run, it's quite likely that all three of these result in very similar/identical code. – Tom Fenech Nov 03 '17 at 15:41
  • 6
    best to google `js perf {feature}` most of the time to get the answer... see https://jsperf.com/destructuring/5 – Meirion Hughes Nov 03 '17 at 15:41
  • 2
    @TomFenech: Depends on whether he/she is transpiling JSX to ES5 or ES2015+. :-) – T.J. Crowder Nov 03 '17 at 15:43
  • @TomFenech Great point!! – Christian Bangert Nov 03 '17 at 15:43
  • 8
    The general answer is: "It depends, and may be faster or slower or the same. But it **extremely** unlikely to make a real-world difference; don't worry about it until/unless you identify a problem and find that it's related to X." (where X is the thing you were worrying about prematurely). – T.J. Crowder Nov 03 '17 at 15:44
  • 3
    The answer to questions like this is ALWAYS the same. Test yourself in whatever Javascript environment you care about right now. Then, don't assume that test result applies to any other Javascript environment either now or a year from now. This stuff is often different in every environment and changes with time. If you're micro-optimizing a statement for performance in a particular environment, you have to develop your own tests to see what works best for you. And, before you spend any time doing that, you should prove to yourself that a difference would actually matter. – jfriend00 Nov 03 '17 at 15:45
  • 9
    This is one of the things you should *optimise for readability* instead of making premature microoptimisations for speed. – Bergi Nov 03 '17 at 15:52
  • @Bergi So true! One can make a gigabyte program of just one chained statement. alpha()...omega(). Who would want to maintain it? Did I just dis functional reactive programming, oops. – Josef.B Dec 06 '18 at 07:15

3 Answers3

36

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.

nikk wong
  • 8,059
  • 6
  • 51
  • 68
  • 6
    The performance difference between regular args and destructuring point stands, but the two functions being compared aren't equivalent to ops. `function add(opts){ const number1 = opts.number1; const number2 = opts.number2; return number1 + number2; }` would be the comparison – Matt Jun 12 '21 at 04:07
  • 2
    In v8 8.4.371.19-node.18 they end up the same and look a bit more terse now. – Matt Jun 12 '21 at 04:07
  • exactly the explanation i was looking for. Thank you – carinlynchin Sep 30 '21 at 01:06
  • 1
    Does destructuring like that use heap space and cause garbage collection? – Lucien Dec 05 '22 at 15:23
6

There won't be any performance issues as your code will be compiled/minify and so on.

Note that with React, your code will be transpiled which will do the same as

const color = props.color

Check the result on the babel compiler online tester

saketh
  • 803
  • 1
  • 10
  • 24
yuantonito
  • 1,274
  • 8
  • 17
-2

I wondered the same. I suppose destructing would consume more memory. While accessing object properties or array elements through their reference, we are accessing the same memory location. When an object or array is destructured, if the values are primitives, the values are copied into a new location. So, destructuring does consumes more memory than accessing through object properties.