Nested functions vs. chaining methods vs. a && sequence of functions - javascript

Good evening/morning (depending of your place),
I'm a newbie 'developer' (JS/Meteor platform), and every day I discover a new thing about JS. Knowing my low level, It is not that hard...
I'm currently wondering the best way/practice to code a switch(true).
More precisely I have a Switch statement with something like 20 cases.
Currently, I decide not to nest some cases together, I find it less easy to read. So my statement looks like something like this:
switch()
case 1
case 2
case 3
case 4
case 5
case 6
...
default
Instead of something like:
switch()
case 1
if
elseif
else
//or
case 2
switch()
case 2.1
case 2.2
My question is: each case tests something like 5+ functions. So a case is basically written this way:
case ( function1()
&& function2()
&& function3() == null
&& typeof abc[1] === 'undefined'
&& function4() === 'xyz') : //etc...
Is there a better way to chain functions?
I'm currently looking at chaining method in a jQuery way: function().function2().function3()... But I don't know if it exits a better way to deal with this kind of situation.
I will be delighted to get your feedback/advice and any reading/lecture you would recommend. I also hope this question is "right" for SO.
Thank you very much.

You shall always strive against small functions to increase readability. It might be a good idea to group function calls in new functions. The faster you can determine what a function does the better. Try to only have things relevant to the current function, for example:
You are supposed to fetch a lot of information about a person but the information is spread into different sources forcing you to have one function for name, one for age, one for shoe size and so on.
Instead of writing it like
case 1:
var person = {
name: getName(),
age: getAge(),
showSize: getShowSize()
};
You could write it like
case 1:
var person = getPerson();
And the the getPerson function
function getPerson() {
return {
name: getName(),
age: getAge(),
showSize: getShowSize()
}
}
In your 20 cases I'm sure there are logical groups of functions that is used in several cases. Try to group them together if they have any logical connections. With a switch as large as with 20 cases I would try to not write to much code in every case since it would probably make it difficult to see what the function does.
I hope I got your problem and at least gave you some advices you find useful.

Related

Can this be written in a switch statement?

I am writing a Safari extension, and would like to detect what page (url) I am currently on, and do things accordingly.
Right now my code looks something like:
if (linkHas("facebook.com")) {...}
else if (linkHas("google.com")) {...}
else if (linkHas("yahoo.com")) {...}
where linkHas() is a function that basically returns 1 if it has the parameter, and 0 otherwise.
Is it possible to write this one single switch statement? I've read somewhere that switch statements are implemented as hash tables if there are more than 5 options. For a small script like mine, the speed probably doesn't really matter much here, I'm really just trying it as an exercise.
The simple, and straight answer is no.
The switch expression has to be/return a value, that is evaluated against the value of each case. As JCOC611 has actually demonstrated, it can be done, but I beg you, don't :)
There is probably definitely a better way of implementing what you're after, but that wasn't your question, so I'll leave it at that.
EDIT
In fact, let me show you a better way.
function doFacebookStuff() {
console.log('Hello Facebook!');
}
function doGoogleStuff() {
console.log('Hello Google!');
}
function doYahooStuff() {
console.log('Hello Yahoo!');
}
var domainActions = {
'facebook.com': doFacebookStuff,
'google.com': doGoogleStuff,
'yahoo.com': doYahooStuff
}
var matched = Object.keys(domainActions).filter(function(domain) {
if (linkHas(domain)) {
domainActions[domain]();
return true;
}
});
console.log('matched domains:', matched);
You can also replace .filter() with .some(), to have it stop at the first match it finds.
Edit: Disclaimer: the following is something you should not do, but is there for reference purposes only. Don't let people tell you you can't, but listen when they say you shouldn't.
The very naive way:
switch(true){
case linkHas("facebook.com"):
// ...
break;
case linkHas("google.com"):
// ...
break;
case linkHas("yahoo.com"):
// ...
break;
}
This has absolutely no performance benefits though. In fact, it might be slower if all the functions are evaluated before the equality tests are performed.
The long way would be to refactor linkHas to be getLinkDomain and check on whatever that returns.
In fact, lets do that. Using the convenient function extractDomain, written by lewdev, you can:
var domain = extractDomain(link);
switch(domain){
case "facebook.com":
// ...
break;
//...
}
Create an "enumeration" of domains to avoid magic strings.
Create a function "getDomain" that returns one of said enumeration.
Create your own hash table called "actions" using an object literal, keyed on said enumeration values. Hash table values can be functions containing the logic to run for that key.
Then write:
actions[getDomain()]();

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?
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
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).
Generally else-if has better performance than if chain. But to use switch case in such a case would be the best choice.
The efficient way to check is switch statement rather than if,
switch(num) {
case 1:
do something;
break;
case 2:
do something;
break;
default:
default do something;
}
The better approach especially for big codes is an if else statement(or even better case).
Using multiple if statements leads the pc to do unnecessary calculations.
For example:
if (5 > 3){
alert("True");
}
else{
alert("False");
}
This is a boolean expression.In the above example the cpu checks the if(5 > 3) which returns true and stops(It won't execute or check the else).
The same but using multiple if
if (5 > 3){
alert("True");
}
if (5 < 3){
alert("False")}
It will do the same as the previous code but now it will execute 2 calculations instead of one

Javascript What is best practice using IF or SWITCH or "dynamic function name" in this case

I am looking for a best practice in this hypothetical situation.
In the example below the function changeGallery0() is a unique function that is Not the same as changeGallery1(), changeGallery2(). They can not be modified to solve this. But each function does take the exact same data (newArrayData)
This code seems "ugly" but works properly. It would become more ugly with 20 galleries. I realize some of this problem exists with the calling unique functions, but it helps illustrate my question.
Using a SWITCH case seems to be more proper. But does it have any advantage over this IF based solution? It seems like a "dynamic function name" (does that exist) would make sense?
Thank you!
if (a == 0) changeGallery0(newArrayData);
if (a == 1) changeGallery1(newArrayData);
if (a == 2) changeGallery2(newArrayData);
if (a == 3) changeGallery3(newArrayData);
You could try something like this:
var fn = window['changeGallery' + a];
if (typeof fn === "function") {
fn.apply(null, newArrayData);
}
The first argument to "apply" would be "this" in your function call.
You could do
window["changeGallery" + a](newArrayData);
I think it would be better to use a for loop. You can place functions inside an array.
var funcArray = [function1, function2 , function3, ...];
There is one thing you need to know about this that is how branching will occur with if else or switch.
With if else if a is 0 the first one will be hit and then you miss rest of 3 but still need to check condition.
With switch you will have branches done but actual code will have a break after one and not check rest of conditions.
You can achieve same with if by using else statements like
if a is not 0 then check if its 1 otherwise no need to do so
If a is not 1 then check if its 2 otherwise no need to do so
this would create nested if else statements that are similar to a switch branching and switch would read better in code so use that.

Is it a good idea to use a switch with fallthrough to handle default arguments in Javascript?

I have recently learned that you can use a neat switch statement with fallthrough to set default argument values in Javascript:
function myFunc(arg1, arg2, arg3) {
//replace unpassed arguments with their defaults:
switch (arguments.length) {
case 0 : arg1 = "default1";
case 1 : arg2 = "default2";
case 2 : arg3 = "default3";
}
}
I have grown to like it a lot, since not only is it very short but it also works based on parameters actually passed, without relying on having a special class of values (null, falsy, etc) serve as placeholders as in the more traditional versions:
function myFunc(arg1, arg2, arg3){
//replace falsy arguments with their defaults:
arg1 = arg1 || "default1";
arg2 = arg2 || "default2";
arg3 = arg3 || "default3";
}
My inital though after seeing the version using the switch was that I should consider using it "by default" over the || version.
The switch fallthough makes it not much longer and it has the advantage that it is much more "robust" in that it does not care about the types of the parameters. In the general case, it sounds like a good idea to not have to worry about what would happen with all the falsy values ('', 0, null, false ...) whenever I have to make a function with default parameters.
I would then reserve the arg = arg || x for the actual cases where I want to check for truthyness instead of repurposing it as the general rule for parameter defaulting.
However, I found very few examples of this pattern when I did a code search for it so I had to put on my skeptic hat. Why didn't I find more examples of this idiom?
Is it just now very well known?
Did I not search well enough? Did I get confused by the large number of false positives?
Is there something that makes it inferior to the alternatives?
Some reasons that I (and some of the comments) could think of for avoiding switch(arguments.length):
Using named parameters passed via an object literal is very flexible and extensible. Perhaps places where more arguments can be optional are using this instead?
Perhaps most of the time we do want to check for truthyness? Using a category of values as palceholders also allows default parameters to appear in the middle instead of only at the end : myFunc('arg1', null, 'arg3')
Perhaps most people just prefer the very short arg = arg || "default" and most of the time we just don't care about falsy values?
Perhaps accessing arguements is evil/unperformant?
Perhaps this kind of switch case fallthrough has a bad part I didn't think about?
Are these cons enough to avoid using switch(arguments.length) as a staple default argument pattern or is it a neat trick I should keep and use in my code?
Since the question has been updated, it's really a matter of opinion. There are a number of javascript features that many people suggest avoiding, such as switch and ternary. This is why there is not a lot of information on some of those features.
The reason that suggestion is made is because many people miss-use those features and create problems in their code. The bugs are sometimes difficult to detect and it can be difficult for others to understand what your code is doing (particularly those unfamiliar with javascript or new programmers).
So if you like to do it that way, and you're not worried about the opinions (or skill level) of anyone working on your code. By all means, your approach will work. I have used the switch statement myself on occasion, and while I don't think it's really "good" or "bad", it's hard to find a situation that requires it.
You asked how I might go about this without an if-else chain:
function myFunc(args) {
var allArgs = {
arg1:"default1",
arg2:"default2",
arg3:"default3"
};
for (var key in args) {
allArgs[key] = args[key];
}
}
myFunc({arg1:null, arg3:'test'})
Just a guess, but Doug Crockford discourages the use of switch statements in 'JavaScript: the Good Parts.' His logic is that switch statements are a common source of bugs because it's difficult to locate them when using 'fall through' logic. It's easy to see when a case is triggered, but it's often difficult to determine if every case in a result set has been covered, especially if it's not your code.

if..else vs if(){return} [duplicate]

This question already has answers here:
Using 'return' instead of 'else' in JavaScript
(13 answers)
Closed 5 years ago.
In the following example - given that the return value isn't of any importance - is there a reason to prefer either method over the other?
// Method 1
function (a, b) {
if (a == b){
// I'm just interested in
// the stuff happening here
} else {
// or here
}
return true;
}
// Method 2
function (a, b) {
if (a == b){
// I'm just interested in
// the stuff happening here
return true;
}
// or here
return true;
}
It seems that best practices (mostly by places I've worked for) is to set default values at the top of a method or function and only change those values if some condition occurs. Thus, the use of else is not needed so Method 2 is preferred.
Since the example is JavaScript, special attention needs to be paid in regards to code size. So Method 2 would create less code for the same functionality, furthering its argument as the preferred.
However, if you have more than 2 possible conditions, an else or else if cannot be avoided. However, most places I've worked prefer a Switch Case in these situations.
I would prefer Method 1 because it is less confusing to read. Also, less duplicate code.
I would base my decision on clarity of code and readability, i.e.:
Choose method 1 when you need to do more stuff in the block after the if-block.
Choose method 2 when you only need two blocks of code, it's then clearer to read
Choose method 1 again in cases where you explicitly think your readers wouldn't understand your cryptic code without the word "else"; this is common when the blocks become larger than a few lines.
Many of today's programmers consider less indentation easier to read and I agree. In which case general preference should go to using the second method.
I would recommend method 1 as it is more readable and self documented.
Any modern browser's interpreter should eliminate any performance advantage in either direction.
There are a couple of reasons method 1 is preferable that haven't been mentioned yet. Having a single point of exit makes any future modifications that require an action common to both branches easier and less likely to be buggy (because the author missed the early return. Similarly, in some cases it makes debugging easier, by providing a common place to put a breakpoint or alert().
Readability here really depends on the role of the function.
If this function will ALWAYS return true, then I would prefer the Method 1 It is clear because it only returns in one place, and it is easy to see it will always be true.
In the above case, Method 2 is more confusing. It returns in multiple places, and is more confusing thusly. Consider a developer unnecessarily traversing possible branches and then seeing how they affect the return value. In this simple case, it is not as big of a deal, but when you get more elaborate conditionals, I would really avoid this approach.
I would only use Method 2 if you have very little code in the if block. Such as something that would deal with an edge case.
Hope that helps.

Categories