DEV Community

Cover image for 10 Clean code examples (Javascript).
Ibeh Ubachukwu
Ibeh Ubachukwu

Posted on • Edited on

10 Clean code examples (Javascript).

1. Assigning a value to the same thing conditionally using ternary operators.

  
a > b ? foo = 'apple' : foo = 'ball'; 

✔️  
foo = a > b ? 'apple' : 'ball';
Enter fullscreen mode Exit fullscreen mode

2. Assigning the same value to a specific object property conditionally.

  
c > d ? a.foo = 'apple' : a.bar = 'apple';

✔️  
a = { [c > d ? 'foo' : 'bar']: 'apple' };
Enter fullscreen mode Exit fullscreen mode

3. Exporting multiple variables

 
export const foo;
export const bar;
export const kip;

✔️ 
export const foo, bar, kip;
Enter fullscreen mode Exit fullscreen mode

4. Declaring and assigning variables from object properties.

  
const a = foo.x, b = foo.y;

✔️
const { ['x']: a, ['y']: b } = foo;
Enter fullscreen mode Exit fullscreen mode

5. Declaring and assigning variables from array indexes.

  
let a = foo[0], b = foo[1];

✔️
let [a, b] = foo;
Enter fullscreen mode Exit fullscreen mode

6. Getting multiple elements from the DOM.

  
const a = document.getElementById('a'),
b = document.getElementById('b'),
c = document.getElementById('c');
d = document.getElementById('d');

✔️
const elements = {};
['a', 'b', 'c', 'd'].forEach(item => elements = { 
  ...elements, 
  [item]: document.getElementById(item) 
});
const { a, b, c, d } = elements;

/*
For this to work your elements ID's must be 
able to be valid Javascript variable names
and the names of the variables in which you store
your elements have to match with that elements' ID.
This is good for naming consistency & accesibility.
*/
Enter fullscreen mode Exit fullscreen mode

7. Use logical operators for simple conditionals.

  
if (foo) {
  doSomething();
}

✔️
foo && doSomething();
Enter fullscreen mode Exit fullscreen mode

8. Passing parameters conditionally.

  
if(!foo){
  foo = 'apple';
}
bar(foo, kip);

✔️
bar(foo || 'apple', kip);
Enter fullscreen mode Exit fullscreen mode

9. Dealing with lots of 0`s.

`

  
const SALARY = 150000000,
TAX = 15000000;

✔️
const SALARY = 15e7,
TAX = 15e6;
Enter fullscreen mode Exit fullscreen mode


``

10. Assigning the same thing to multiple variables.

``

  
a = d;
b = d;
c = d;

✔️
a = b = c = d;
Enter fullscreen mode Exit fullscreen mode


``

Bonus⭐ (A deugging tip)

Debugging with console.log() can be a pain having to write it
over and over again. You can shorten it by object destructuring
assignment.

``

const { ['log']: c } = console;
c("something");
Enter fullscreen mode Exit fullscreen mode


``

Now Instead of having to write out console.log()
you can just write c() which is easier to write for
faster debugging.

Thanks for reading!🎉.

View my github

Top comments (70)

Collapse
 
jamesthomson profile image
James Thomson

Myself, I would call most of these "less code" examples, not necessarily "clean code". Imo, clean code is legible code. A lot of these examples require the developer more mental fatigue. Some of these I do, but others I definitely avoid, especially #10.

Collapse
 
dasdaniel profile image
Daniel P 🇨🇦

☝💯
A bunch of these seem more clever than clean.

I consider the #1 priority of the code to easily communicate what is happening.
consider these two examples

const a = foo.x, b = foo.y;

✔️ const { ['x']: a, ['y']: b } = foo;

I don't know if I'm "over-indexing" on my experience here, but I'd say the "incorrect" example is easier to comprehend.

Collapse
 
jamesthomson profile image
James Thomson

The "incorrect" version is definitely less cognitive load. I also prefer individual const definitions as well for that extra level of legibility when scanning the code.

Collapse
 
charleshimmer profile image
Charles Himmer • Edited

#4 could also be written much simpler like this:
const { x: a, y: b } = foo;

Collapse
 
ishwarm81238332 profile image
Ishwar More

But there is no b. keys are different and value is same (here a).

const { ['x']: a, ['y']: a } = foo; will not be possible

Thread Thread
 
jamesthomson profile image
James Thomson

It's re-assigning the value. ['y']: b assigns the value of y to b so you can now access it as b.

Collapse
 
weironiottan profile image
Christian Gabrielsson

Agreed with you, Code Readability should trump trying to shave off lines of code.

Collapse
 
darkwiiplayer profile image
𒎏Wii 🏳️‍⚧️

I don't think #10 is all that bad. It's a bit confusing to figure out which variable gets assigned to the others, but that's easily figured out to be the right-most variable. Logically speaking, it does make sense: all those variables end up being equal to each other.

Collapse
 
jamesthomson profile image
James Thomson

It's a bit confusing to figure out which variable gets assigned to the others

That’s exactly my point. It causes mental fatigue. If you have to stop and think about how something as simple as this is constructed then it reduces the legibility of the code. It’s not that hard to figure out, but it still isn’t absolutely clear and imo it’s unnecessary.

Thread Thread
 
mellen profile image
Matt Ellen-Tsivintzeli

10 could be really bad in a language like c++ with operator overloading. But, yeah, the "incorrect" version is much clearer, regardless.

Thread Thread
 
dasdaniel profile image
Daniel P 🇨🇦

what about const [a, b, c] = [d, d, d]; ?

brent approves

Collapse
 
redbossrabbit profile image
Ibeh Ubachukwu

Thank you. I should probably work on my article title naming 😅

Collapse
 
khangnd profile image
Khang

Considering all the feedback, I do believe this article should be renamed to avoid misleading to learners, seriously.

Thread Thread
 
redbossrabbit profile image
Ibeh Ubachukwu

Nah..😄. I think the feedback will help people understand better what clean code is and isn't.

Collapse
 
valeriavg profile image
Valeria

When dealing with lots of zeros it's also possible to use underscore to separate ranks:

const num= 10_000_000;
Enter fullscreen mode Exit fullscreen mode
Collapse
 
redbossrabbit profile image
Ibeh Ubachukwu

Thanks. Finally a responsible dev community! 😄

Collapse
 
valeriavg profile image
Valeria

Haha, no worries!)

Collapse
 
redbossrabbit profile image
Ibeh Ubachukwu

I meant to say responsive*. But I guess responsible works fine too. Autocorrect issues😤

Collapse
 
e11y0t profile image
Elliot Wong

Woah didn't know this until now! This will defo help with code readability, thanks :)

Collapse
 
wialy profile image
Alex Ilchenko • Edited

shortcleanreadable

2 Instead of

a = { [c > d ? 'foo' : 'bar']: 'apple' };
Enter fullscreen mode Exit fullscreen mode

it's better to split it into couple lines

const key = c > d ? 'foo' : 'bar';
const a = { [key]: 'apple' };
Enter fullscreen mode Exit fullscreen mode

4 might be even cleaner

const { x: a, y: b } = foo;
Enter fullscreen mode Exit fullscreen mode

6 seems overcomplicated, maybe something like

const [a, b, c, d] = ['a', 'b', 'c', 'd'].map(document.getElementById)
Enter fullscreen mode Exit fullscreen mode

7 questionable, I'd say if construction is easier to understand, especially for juniors joining the project

8 use ?? instead of || - that way you'll not override 0 value

9 less known JS feature - you may use underscore to divide long numbers

const a = 1_000_000;
console.log(a); // 1000000
Enter fullscreen mode Exit fullscreen mode

bonus just use a debugger or create an IDE snippet.

Collapse
 
sergei profile image
Sergei Sarkisian • Edited

So, if initially a has several properties

let a = { foo: 'some', bar: 'example' };
Enter fullscreen mode Exit fullscreen mode

Then after

c > d ? a.foo = 'apple' : a.bar = 'apple';
Enter fullscreen mode Exit fullscreen mode

a will have same amount of properties.
But after

a = { [c > d ? 'foo' : 'bar']: 'apple' };
Enter fullscreen mode Exit fullscreen mode

It will hav only 1 property. It's not even the same!

Collapse
 
chasm profile image
Charles F. Munat • Edited

On looking deeper, I find that roughly half of these are plain wrong. It's not even a matter of opinion.

For number 2, this:

// BAD
c > d ? a.foo = 'apple' : a.bar = 'apple'
Enter fullscreen mode Exit fullscreen mode

assigns 'apple' to foo or bar depending on the values of c and d. It leaves the other keys of a alone.

This:

// BAD
a = { [c > d ? 'foo' : 'bar']: 'apple' }
Enter fullscreen mode Exit fullscreen mode

reassigns a (which means it is not a const), wiping out all previous key-value pairs. It's also pretty unreadable. Both mutate a.

They are not equivalent.

Better would be to use the spread operator:

// BETTER
const key = c > d ? 'foo' : 'bar'
const b = {
  ...a,
  [key]: 'apple'
}
Enter fullscreen mode Exit fullscreen mode

Number 3 is just plain wrong. const must be assigned when it is declared, so the example cannot occur in real code. Smart code avoids let as much as possible, and if necessary strives to assign at the same time as it is declared. So an actual example would be more like:

// BAD
export const foo = 'some bit of text',
  bar = 'some more text',
  kip = 666
Enter fullscreen mode Exit fullscreen mode

This is difficult to read (worse if you try to do it on one line). So much cleaner to write:

// BETTER
export const foo = 'some bit of text'
export const bar = 'some more text'
export const kip = 666
Enter fullscreen mode Exit fullscreen mode

At a glance I can see exactly how many variables I've declared and assigned and that each is exported and each is not reassignable.

Shorter or terser is not the same thing as cleaner, more intuitive, or more readable. Sometimes duplication is better.

Number 4 is needlessly verbose and difficult to read. This:

// BAD
const { ['x']: a, ['y']: b } = foo
Enter fullscreen mode Exit fullscreen mode

Should be this:

// BETTER
const { x: a, y: b } = foo
Enter fullscreen mode Exit fullscreen mode

Number 5 is OK, but number 6 is pointlessly mutable. Why? Instead of this:

// BAD
const elements = {};
['a', 'b', 'c', 'd'].forEach(item => elements = { 
  ...elements, 
  [item]: document.getElementById(item) 
});
const { a, b, c, d } = elements;
Enter fullscreen mode Exit fullscreen mode

Do this:

// BETTER
const [a, b, c, d] =
  ['a', 'b', 'c', 'd'].map(id => document.getElementById(id))
Enter fullscreen mode Exit fullscreen mode

The variables are positional, so no reason their names have to match the IDs. You can make them better. You need better variable (and ID) names in general. These are terrible examples.

Number 7: instead of this:

// BAD
foo && doSomething()
Enter fullscreen mode Exit fullscreen mode

But the full if statement is more obviously a guard and more scannable. Don't make terseness the enemy of readability.

// BEST
if (foo) {
  doSomething()
}
Enter fullscreen mode Exit fullscreen mode

Number 8 is OK, but number 9 needs work. Who can read this?

// BAD
const SALARY = 15e7,
TAX = 15e6
Enter fullscreen mode Exit fullscreen mode

How many people can do the math in their head? Few, I bet. But use the underscore and both the magnitude and the difference in magnitudes become clear:

// BETTER
const SALARY = 150_000_000
const TAX = 15_000_000
Enter fullscreen mode Exit fullscreen mode

Re number 10, assigning the value of one variable to another is generally something to avoid as it's not clear what you're assigning (unless you've named the variables very well). But even if you're assigning, say, a string, it is better to stack them. This:

// BAD
a = b = c = 'some text
Enter fullscreen mode Exit fullscreen mode

Is easily missed and takes a moment to parse. And you probably have to keep reminding yourself that a, b, and c have the same value. (Why on Earth would you need 3 variables with identical values -- unless you're mutating them, which... just don't.)

Much better:

// BETTER
const duplicateA = 'some text'
const duplicateB = 'some text'
const duplicateC = 'some text'
Enter fullscreen mode Exit fullscreen mode

The bonus is half a good idea, and half a bad one. Instead of this:

// BAD
const { ['log']: c } = console
c("something")
Enter fullscreen mode Exit fullscreen mode

Do this:

// BETTER
const log = console.log

log('something)
Enter fullscreen mode Exit fullscreen mode

Now you know what it's doing.

I guess posts like this spur discussion, but for the unwary newbie they are strewn with land mines, doing them a disservice. So BEGINNERS BEWARE! Much of what you read online is written by people who haven't really done their homework. Don't let their mistakes be yours.

Collapse
 
sergei profile image
Sergei Sarkisian

That's the first thing I noticed when saw the code. Great explanation.

Collapse
 
andrewbridge profile image
Andrew Bridge • Edited

I think these are great easter eggs one might use for code golf. The fact Javascript can do these things is probably worthwhile knowing to be more comfortable with the language.

However most of these are trick shot one liners that I'd probably point out as being too fiddly if I saw them in a code review.

Snippet 2 took me long enough to understand what was going on that I'd probably just flag it without going any further to even check if the logic was correct. However the assignment within the ternary (the example of "wrong" code) is also the type of thing I'd consider overly complicated. A nice, clear if statement would've been fine.

Snippet 8 is another where I would far prefer to read the first, "wrong" example and would understand it straight away.

Snippet 6 has been mentioned several times, but the "correct" example is not only more complicated, but actually far less efficient. The "wrong" example does 4 simple assignments, the Javascript engine will be able to optimise these 4 lines really easily. Your "correct" code:

  • creates a new object
  • creates a new array object
  • iterates over that new array with a new function
  • spreads and reassigns the object every time into yet another new object
  • finally dumps the object, assigning the values to the local scope

The Javascript engine uses more CPU cycles running it and has to allocate more memory to store all that extra state, and even worse, the garbage collector now has a whole mess to clean up afterwards that doesn't get used ever again.

Just to balance things out, #7, #9 and your bonus tip are genuinely useful shortcuts, that make things easier to read and work with, and I use all three in everyday development. Great things to point out!

I think the main takeaway is that clever tricks are fun to work out and discover, but they're rarely better than the simplest possible code. Also "Clean code" !== shortest code. In fact, it's often better to have 5 lines instead of one if it makes it clearer what's going on. After all, if I want my code smaller and shorter, I'll put it through a minifier and an uglifier before I ship it to production, and let the computers deal with the one liners!

Collapse
 
redbossrabbit profile image
Ibeh Ubachukwu

More knowledge! 🧠💪

Collapse
 
_genjudev profile image
Larson • Edited

Like it.

6 could be better by just creating the object directly. Its faster and better to read.

Also dont to 10. If u coding like that there is a good chance u get race conditions. Also by working with objects:

let a = b = c = {"a":"b"}
a.a = "p"

console.log(c)
// { a: "p" }
Enter fullscreen mode Exit fullscreen mode
Collapse
 
redbossrabbit profile image
Ibeh Ubachukwu

Thanks! Learning never stops.

Collapse
 
jankapunkt profile image
Jan Küster • Edited

I think clean code is still a very debatable topic. To me, personally, clean code is code with improved readability or improved contextual information:

Example:

const g  = 9.81 // unclear
const GRAVITY_OF_EARTH = 9.81 // clear
Enter fullscreen mode Exit fullscreen mode

Same goes for preparing structures for commenting code:

hard to read

if (condition) {
  // long block comments about 
  // what this branch actually does
  ...
} else {
  // long block comments about 
  // what this branch actually does
  ...
}
Enter fullscreen mode Exit fullscreen mode

easier to read:

// long block comments about 
// what this branch actually does

if (condition) {
  ...
}

// long block comments about 
// what this branch actually does

else {
  ...
}
Enter fullscreen mode Exit fullscreen mode
Collapse
 
yaireo profile image
Yair Even Or • Edited

Number 4...?! what is going on there.. it should be as follows:

var foo = {x:1, y:2}
var {x:a, y:b} = foo
console.log(a,b)
Enter fullscreen mode Exit fullscreen mode
Collapse
 
redbossrabbit profile image
Ibeh Ubachukwu

I guess that works too! 😅

Collapse
 
jivkojelev91 profile image
JivkoJelev91

Everything is fine, except 6. There is no need to create a new object, new array, loop over them and so on, this is neither clean, neither fast.

Collapse
 
thefern profile image
Fernando B 🚀 • Edited

Yup he had me sold on most, except 6 and 10. One note on 6 might be a good case, if you're looping through a known array, but for this specific example I don't think is worth the hassle.

Collapse
 
redbossrabbit profile image
Ibeh Ubachukwu

Thanks!. It thought it would be helpful when you have to get alot of elements from the DOM. I guess its more of 'less' code than 'clean' code 😄

Collapse
 
weironiottan profile image
Christian Gabrielsson

Full heartedly disagree with 7, not every developer knows JS specific code shortening syntax, but every developer knows an If statement, it honestly frustrates me when a developer goes out of their way to reduce code only for it to become less readable. Code readability trumps trying to reduce lines of code IMO

Some comments may only be visible to logged-in visitors. Sign in to view all comments.