Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Which is better If-Else-If chain or multiple If

Say I have a random number.

Which is more efficient:

if (num == 1) {

} else if (num ==2) {

} else if (num == 3) {

} else if (num == 4) {

} else if (num == 5) {

} else {};

or

if (num == 1) {};
if (num == 2) {};
if (num == 3) {};
if (num == 4) {};
if (num == 5) {};

is there much of a different performance-wise?

Or should I do a switch chain?

like image 650
AlwaysNeedingHelp Avatar asked Feb 12 '23 04:02

AlwaysNeedingHelp


2 Answers

If you have a small number of situations that you want to handle separately (and you are using a number to differentiate), then the Switch statement would provide clearer logic to someone (including you) who tries to read or modify your code.

If / else if chains may be mis-perceived later

Successive If statements mean you are constantly checking for a situation you know is wrong

like image 126
ErstwhileIII Avatar answered Feb 15 '23 09:02

ErstwhileIII


A bit late to the party, but apart from the other valid answers:
what if you could call your intended subcode (almost) directly (if you have a LOT of options)....

I have a different solution (you were open other options):

var switchArr=[ //skipping 0
, function(){ /* do stuff for 1 */ }
, function(){ /* do stuff for 2 */ }
, function(){ /* do stuff for 3 */ }
]; // you could also set them directly if you have irregular (large) intervals

if(switchArr[num]){
  switchArr[num]();
} else {
  //defaults
}

EDIT: alternatively (expanding on the above concept) using an object (because order does not have to be guaranteed, as array does) and some closure and a simple way to pass num to the handler function:

var switcher=(function(){
  var N, F={
   default: function(){ alert('default function for '+N); }
  ,      1: function(){ alert('doing stuff for '+N);  }
  ,      2: function(){ alert('other stuff for '+N);  }
  ,      5: function(){ alert('I am function '+N);  }
  };

  return function(n){ F[N=n] ? F[n]() : F.default(); };
})();

num=3; switcher(num);  // default function for 3
num=5; switcher(num);  // I am function 5

Depending on use-case one of the above (or a hybrid) could be a better solution. If execution-time is at a prime, don't use the helper-function (that does the check) since that saves a function-call.

EDIT 2:

In the comments is asked for the benefit of this alternative:

Contrary to popular belief (that javascript/ecmascript uses a switch to 'directly jump' to a start-point in a codeblock), the switch statement in modern browsers evaluates the case expressions using the === strict comparison operator (so the expressions must match without any type conversion) in the order in which they (case not default) appear until it finds a value that matches (after which it will 'fall through' until a break or a return when inside a function is encountered or the codeblock ends, hence default can appear anywhere in the codeblock, not only at the end).
This is because the ECMAScript v3 standard allows each case to be followed by an arbitrary expression.

Note (for older browsers) that the switch statement is implemented in JavaScript 1.2, but it does not fully conform to the ECMAScript specification. In JavaScript 1.2, case expressions must be literals or compile-time constants that do not involve any variables or method calls. Furthermore, although ECMAScript allows the switch and case expressions to be of any type, JavaScript 1.2 and JavaScript 1.3 require that the expressions evaluate to primitive numbers, strings, or boolean values.
Source: JavaScript: The Definitive Guide (4th ed)

See the resemblance with an if-chain? The difference is the ability to fall through (until end/break/return).
The amount of comparison work (in an example where you have a LOT of different cases) is thus the same (at least, per spec, not guarantied per interpreter implementation, which wildly varies among versions).

A lot of (generally not frowned upon) optimization involves tweaking code to have a predictable relatively scalable (in regard to the host's capability's) execution-time. In my suggestion (intended to show ways of thinking outsize of the box), you have a small fixed number of steps before your payload executes (something that you can guarantee according to the language-spec).

That leaves 'understandability' which is a tricky question because that is highly related to 'intent' and 'readability', thus opening the can of worms regarding different viewpoints/options/mantra's/best-practices, much of which hold different value (or plain simply don't/shouldn't apply) to 'javascript' (for web-based applications) (in my opinion).
There can be thought of many different approaches using comments etc (or the second example that uses an object) and different coding-styles/patterns that would alleviate initially perceived hindrance of 'clear code'.
After-all, ideally one should have good documented 'raw' ((gzip-)pre-optimized where applicable (you don't want to maintain/debug both raw and 'compiled' code)) code, but send minified (without doc/comments minified var-names etc) code to the browser (in production).

Finally as to performance, again depending on what one is trying to do (and lot of cases are involved), the array version (without helper function) will be smallest and fastest for a range of numerical cases. The object then has its strength in (irregular) numerical intervals and string-based switches. However, as always, one must test (supported target-)hosts/browsers to assess their performance. However up to now, in my experience when dealing with a lot of cases, this one is a winner.

Final note, when dealing for instance with a known set of cases, one wouldn't even need to check if the case exists, let alone need a helper function.. speed for the win (in such a case).

like image 44
GitaarLAB Avatar answered Feb 15 '23 09:02

GitaarLAB