Learn to Code via Tutorials on Repl.it!

← Back to all posts
JavaScript Code Style
Coder100

JavaScript, unlike many languages, has a very diverse code style. This is probably a combination of not only ASI (Automatic Semicolon Insertion) code style, but also if quotes should be used or not, and type safety.

So without further ado, lets talk about my favorite code style!

Coder100's code style

Semicolons

Semicolons are always required, but beware of ASI.

ASI

ASI automatically inserts a semicolon if the program errors. You can read up here

Quotes

Due to how often we're using single quotes, it is very recommended to use double quotes. Also in lower level languages, double quotes signify a string, and I believe it is wise to adapt that into your coding as well.

However, the exception is when you require double quotes:

Try to minimize escaping, and if there is no need for escaping, just use ".

Spacing

I have always used two spaces, but sometimes I use 4, and sometimes I use tabs. So which one should we use? I flipped a coin between two spaces and tabs and got two spaces, so that's what we are using.

Resolving Paths

Use path.join, not only is it going to make your life easier, it also allows you to make more complex paths.

Destructuring

I haven't found much use for destructuring, but just make sure you add spaces:

Spacing

This code snippet will tell you everything.

Arrow functions

I only use arrow functions as lambdas. You should too. It allows you to define functions anywhere!

Also anonymous functions should always be converted to arrow functions, except for when binding.

Function Definition

I normally call functions before defining them,

however, what you want is really up to you. However, never define functions within loops.

Mutability

Like rust, make sure to define everything as constant. Only when you need to change mutability should you change the const keyword to let.

Objects and Arrays

These can be prefixed with let if you are going to change them. const isn't only for the interpreter, it is also for programmers.

If you want objects to be constant, consider also adding Object.freeze()

Same goes with arrays.

Member Access

The final code style is with member access. Try to use . as much as you can, but use [] for variables and numbers.

Conclusion

Hopefully you like this code style. Finally I have peaked in good coding practices!
In the next tutorial, I will be showing you how to use eslint to enforce this code style :))

See you then!

Credits

Special thanks to @fuzzyastrocat and @Baconman321 for pointing out some edge cases

Voters
Spotandjake
AbilashSree
Wilke000
JorgeCepeda1
RakeshYadav6
SaraYasmin
RiomLawrence
Eli900
AL0YSI0US
SWDeveloper
Comments
hotnewtop
fuzzyastrocat

Pretty good tutorial! However:

Also anonymous functions should always be converted to arrow functions.

That's not the case! They have two different roles and arrow functions will not work in some situations due to their this scoping. (Otherwise anonymous functions would have no purpose in the language at all.) Example:

Also, I have to disagree with the first part on arrow functions. For the example:

For such a trivial example, the function bad is much more succinct. And, such a trivial function should not require a circular dependency, which is the only reason function hoisting is useful. So, I feel that simple one-liners (function = evaluate a single expression) should be expressed as arrow functions, while multiline functions (functions which would require () => { ... statements ... }) should be expressed as function name () { ... }.

Coder100

thanks! yeah, ig I didn't consider many edge cases in this tutorial, thanks for pointing those out, I'll add them @fuzzyastrocat

Coder100

wait a second why doesn't y require binding? It's an anonymous function right? @fuzzyastrocat

fuzzyastrocat

@Coder100 It works just fine like that, no binding needed. That's the point of (and my point with) the function () { } expression. (Try it yourself).

Coder100
realTronsi

@Coder100 why did you make a tutorial on your own opinions -_-

cycle farmer

also for example:

defining functions in loops is fine if you want to programmatically define functions for some reason, just that it's not commonly needed

why is the avoid there, as you stated afterwards, for objects to be constant use Object.freeze()

const != Object.freeze() at all

purely personal preference, using escape characters is arguably even better in most situations since it allows you to utilize all three

Coder100

@realTronsi well the thing is this tutorial was inspired by the standard code style, which is absolutely trash

realTronsi

@Coder100 I just don't know what the purpose of this tutorial is lmao, like it doesn't really teach you anything??? Otherwise decently entertaining ig

fuzzyastrocat

@Coder100 @realTronsi Note that while systematically defining functions in loops is possible, it's very inefficient.

well the thing is this tutorial was inspired by the standard code style, which is absolutely trash

If it's absolutely trash, why did you make a tutorial on it? Shouldn't you make a tutorial on the best way to try to educate people? (Also if it was inspired by the standard code style then everyone's already doing this, so a tutorial isn't needed...)

realTronsi

@fuzzyastrocat I mean if you want to systematically mass define functions that's the way to go, you don't want to do something like

obviously systematically defining functions will be rarely useful though (I can't even think of a great example atm)

fuzzyastrocat

@realTronsi Yeah, definitely.

Highwayman

I flipped a coin between two spaces and tabs and got two spaces, so that's what we are using.

Ahh I see so for every line I flip and...

Coder100
fuzzyastrocat

@Highwayman

Highwayman

HAHA YESS XD
@fuzzyastrocat

Coder100

@fuzzyastrocat

Baconman321

Cool, this is pretty much the same for me (well, the const part no, because a lot of stuff I have to change sooner or later). You forgot hoisting tho. Since JavaScript renders functions first, you don't have to worry too much for functions (and sometimes it's actually very useful), but I recommend staying away from hoisting as much as possible. Also, I recommend putting all the global variables and functions (unless otherwise needed somewhere else) at the top of the program. Makes code cleaner. Also, if you have a function (like a loop) that gets called over and over again, and generate new instances a whole lot, I recommend after you're done with the function to assign it to null, so the garbage collector will collect it.

Coder100

@Baconman321 ah yes, I did forget a lot of things lol

Coder100

@Baconman321 so um I don't really care for hoisting as I normally split functions into many files, and otherwise they don't get called over and over again.

I rarely put functions inside loops, as I usually use things like .map and .foreach

thanks for your advice!

Baconman321

@Coder100 Typically you would do looping if you do game design or anything like that because you have to constantly update the canvas (or whatever you are using).

Coder100

true, typically you would use recursion to achieve that @Baconman321

Baconman321
fuzzyastrocat

@Coder100 @Baconman321

typically you would use recursion to achieve that

What?!?! You'd quickly blow the JS call stack if you used recursion for your main draw loop! Typically, you'd use requestAnimationFrame.

Baconman321

@fuzzyastrocat Yeah. Or it goes really really fast (depends on how you implement it). I think coder100 meant that.

fuzzyastrocat

@Baconman321

depends on how you implement it

No matter how you implement recursion in JS, it's going to blow the call stack if it's unbounded. There is no tail call optimization in almost all standard JS implementations (barring Safari), so if it doesn't blow the stack then it's not recursion.

Baconman321

@fuzzyastrocat I have been able to requestAnimationFrame with the function call, so IDK why then. Yeah, the call stack is a big frustration, but quite easy to avoid.

fuzzyastrocat

@Baconman321 requestAnimationFrame is not recursion, which is why it doesn't blow the stack. (If this isn't what you meant then please tell me.)

Coder100

wait is requestAnimationFrame not just recursion but without stack overflows? @fuzzyastrocat

fuzzyastrocat

@Coder100 No, it's not, since with recursion a function call can return but requestAnimationFrame cannot. (Now, they may be implemented in a similar way, but that's neither here nor there. requestAnimationFrame itself is not recursion.)

Coder100

@fuzzyastrocat hm alright
ill read up on its implementation xD

Baconman321

@fuzzyastrocat I tested.

does not return a stack error. It just gets called.... really fast. I don't know if that's recursive, but that's what I've heard.

fuzzyastrocat

@Baconman321 A few things here. One, try removing the console.log and see if you get a stack overflow. It could be that your console.log's buffer is slow to write and so therefore it's just prolonging the stack overflow for quite a while.

If not, what browser are you using? If you're using Safari, as I mentioned before then that would make sense. Safari is an anomaly in that it performs tail-call optimization — standard JS implementations do not, and therefore that code will not work on most browsers. For example, I tried this on Chrome (removing the console.log so that it will run quicker), and it quickly runs into a stack overflow.

Coder100

be patient, the threshold is like 10k or smth @Baconman321

Baconman321

@fuzzyastrocat I'm using chrome. Still, it goes too fast for me, so I prefer to use requestanimationframe.

fuzzyastrocat

@Baconman321 Let's not just skip away from this issue though, I'm interested. Do you get a callstack error when you remove the console.log? If not, what version of chrome do you use?

EpicRaisin

@fuzzyastrocat @Coder100
lol I've always just done setInterval('draw()', 1)

Baconman321

@EpicRaisin That has problems, as it really depends on CPU usage (if the CPU usage is higher, it goes slower because of lag). It's better to use requestAnimationFrame(draw). If not, use setTimeout recursively, as that can be used as a better setInterval.

fuzzyastrocat

@Baconman321 @EpicRaisin Keep in mind that a recursive setTimeout cannot be relied upon to run forever. See this article for more. So therefore, it is not a better setInterval for the purpose @EpicRaisin described.

Just use requestAnimationFrame and everything will be good :D

(Also @Baconman321 did you see my above comment?)

Baconman321

@fuzzyastrocat I believe that's TCI (tail call optimization). Yes, I do get a callstack error. Any code whatsoever inside a recursive loop like that prevents a callstack error (according to stackoverflow).

Baconman321

@fuzzyastrocat What above comment? Also, you can implement a clearTimeout to prevent the callstack from growing too large. Also, I see you like looking into the very depths of programming languages (like how they actually execute code and stuff), I would love to do that too... but it's pretty complex right now :(

fuzzyastrocat

@Baconman321

Any code whatsoever inside a recursive loop like that prevents a callstack error (according to stackoverflow)

Hmm, I'm confused here. First of all I'm not sure what you mean by "recursive loop", that's kinda an oxymoron, but I assume you mean a recursive call which functions the same as a loop.

Now, if you had tail call optimization you would not get a callstack error. So I'm not sure what your point is there... perhaps you have it backwards, since you say that recursive loops prevent callstack errors when they are really the cause of them?

Also, the above comment was my one asking about continuing the issue. ("Let's not jump away from this though...")

Also, you can implement a clearTimeout to prevent the callstack from growing too large.

But then the loop stops. So now you have to implement some kind of restarting mechanism, and that's just way too complex.

Baconman321

@fuzzyastrocat Yeah, but it would work. Also, settimeout doesn't work well over 1 hour for some reason (or not at all). Uhm, I think TCI is not in use, but basically JavaScript throws a callstack error because you are calling something over and over without doing anything (which is like TCI, otherwise IDK from what I heard it's basically something that prevents the call stack from going oof... ok yea I saw TCI doesn't throw an error nvm). I mean recursive loop as in recursive function (sorry). Also, is there a resource that you use to learn this? I would like to read up about this myself...
IDK why anything inside a recursive function prevents a callstack error either...

fuzzyastrocat

@Baconman321 Okay, your understanding of TCO (not TCI) is a little incorrect. Let me try to clear things up:

All that tail call optimization (TCO) does is convert a recursive call into a loop. That's it. So if you have this code:

TCO will convert that x(); at the end (the one by the // this is the call comment) into this:

This is how TCO prevents the call stack from being overflowed — it converts the function call into a standard loop, which doesn't need a function call and therefore doesn't overflow the call stack.

Uhm, I think TCI is not in use, but basically JavaScript throws a callstack error because you are calling something over and over without doing anything

IDK why anything inside a recursive function prevents a callstack error either

This has nothing to do with it. If you waited long enough, your original example (with a console.log in it) would throw a callstack error. It's just that it takes wayyyyy longer to run because it's having to actually do something (rather than just an empty loop), so it doesn't hit that callstack error as quickly. Because writing to a buffer is incredibly slow, console.loging every loop means it would take a long time. But here's an example that will hit a callstack error quickly, and it does do something in the loop:

This simply logs e every 100th iteration, instead of every single iteration, so it doesn't do as much buffer writing and therefore isn't as slow. But, it still gets a callstack error.

As for a resource, I can't really give you one since I'm not sure. These are some very fundamental misunderstandings of how function calls work, so I'm not really sure of a good resource to clear it up. Really, if you're determined enough and you have access to google you'll be able to find anything. (It's how I've done it.)

So, just remember: a function call is not "linked" to what's inside a function. If you recursively call a function over and over, it will run into a call stack overflow. It just depends how long it will take.

However, if TCO is being used, then your function call will actually be converted into a loop and therefore it won't run into a callstack error (loops don't use the callstack). Note, however, that not all functions can be converted into a loop: the function call must be at the very end of the function ("tail call") to be actually made into a loop. If you're wondering why, I'd suggest reading up on tail call optimization. A google search should suffice.

Baconman321

@fuzzyastrocat IDK what you mean by writing to a buffer, why does console.log need a buffer? Could it be that it needs to wait a bit before accessing the i/o stream (to the console, or is I/O stream not in a console)? I'm confused...

fuzzyastrocat

@Baconman321 The "buffer" I speak of is "the place where console.log outputs everything". No, it does not need to wait before writing (that would be waiting for no reason). It's just that console.log is a very slow operation compared to, say, math (console.log("e") will run very slowly compared to 1 + 2 * 3 - 4 / 5 + 6 * 7 - 8). As for exactly why it's slow, that's getting very deep down and I won't explain it here because I think it would just make things more confusing.

Now, everything is relative — this "slowly" is only on the scale of milliseconds (or even microseconds), so you won't notice it if you just console.log once. But since you're console.loging hundreds and thousands of times in your recursive example, the slowness compounds and becomes extreme.

Baconman321

@fuzzyastrocat Oh ok. I can't find anything explaining what a buffer is used for in console.log... so IDK how I'm gonna know that.

fuzzyastrocat

@Baconman321 The terminology "buffer" might not be used specifically, but "buffer" itself means "a temporary area of memory to transfer or process data". So while that might not have been the perfect terminology to describe it, I think you can probably get the idea from it: the buffer I'm talking about is where all the things that console.log outputs are stored.

That's something that I think might help a lot — don't necessarily look for things exactly as they are, think about how the connect. For instance, console.log outputs things from your code. But where does it output? Well, there must be some kind of temporary memory that stores the things which console.log outputs. This could be called a buffer, it could be called a stream — it depends on the implementation, but both can convey the same meaning.

Coder100

i've never seen buffer outside of C and C++ that's a first for me lol

I know that a buffer can be used for higher level things, but I never considered the dom console a real 'terminal' lol @fuzzyastrocat

Baconman321

@fuzzyastrocat Yeah. I know chrome has a "preserve-log", so it must be something with more memory than something meant to be very "temporarily" reserved...

Baconman321

@Coder100 I highly doubt buffer will only be in low (or lower) level languages. In fact, there is Buffer() in nodejs (I believe). A lot of times, you can make your own buffer (in concept).

fuzzyastrocat

@Coder100 Eh I mean, with modern browsers it's basically a real terminal. Like I said though, depends on the implementation.

fuzzyastrocat

@Baconman321 Yeah, depends on the browser/implementation. Also Chrome might use a buffer, and then move that memory into more permanent memory (the other purpose of buffers).

Baconman321
frissyn

I flipped a coin between two spaces and tabs and got two spaces, so that's what we are using.

Bruh -_-

CursorsDev
Coder100

why break it up? @CursorsDev

CursorsDev

in strict mode trying to modify a frozen object will result in an error

CursorsDev

Use path.join, not only is it going to make your life easier, it also allows you to make more complex paths.

er, the actual reason is for all platform support since linux and gnu uses / while windows uses \...

Coder100

well yeah obviously, but you can also have more complex paths:

@CursorsDev

GatewayDuckYT

some things i like to use with it works best with if else but can be used for alot

insaid of this

try doing

or

try

Using html Temples help alot

Doing this is sad

Try

robinjamess

Well, I must admit, that "the best lies in the middle". Upvoted for statement, that arrow functions will not cover any possible function use cases. They are really designed to solve only a part of the common problems. Just switch to them completely will be an overkill

Coder100

yeah, but that doesn't mean you shouldn't use them by default @robinjamess

Coder100

lol what are those links @robinjamess

potatojs

I haven't found much use for destructuring

are u serious

that's enough for me

Kasey00

Scoping is mucked up in functions. Normal function use this in the scope of the caller, however arrow functions use this in the scope of the callee, a.k.a the sane way

robinjamess

@Kasey00 With () => {} and function () {} we are getting two very similar ways to write functions in ES6. In other languages lambda functions often distinguish themselves by being anonymous, but in ECMAScript any function can be anonymous. Each of the two types have unique usage domains (namely when this needs to either be bound explicitly or explicitly not be bound). Between those domains there are a vast number of cases where either notation will do.

Arrow functions in ES6 have at least two limitations:

Don't work with new and cannot be used when creating prototype
Fixed this bound to scope at initialisation
These two limitations aside, arrow functions could theoretically replace regular functions almost anywhere. What is the right approach using them in practice? Should arrow functions be used e.g.:

"everywhere they work", i.e. everywhere a function does not have to be agnostic about the this variable and we are not creating an object.

only "everywhere they are needed", i.e. event listeners, timeouts, that need to be bound to a certain scope
with 'short' functions, but not with 'long' functions
only with functions that do not contain another arrow function
I am looking for a guideline to selecting the appropriate function notation in the future version of ECMAScript. The guideline will need to be clear, so that it can be taught to developers in a team, and to be consistent so that it does not require constant refactoring back and forth from one function notation to another.

DynamicSquid

@robinjamess @Kasey00 Thanks for the info, but please don't include irrelevant links :)

G0RG3

This will really help!

Coder100

yay! Glad I helped you! @YashasShah

potatojs

js is the best.

liammandes

Due to how often we're using single quotes, it is very recommended to use double quotes. Also in lower level languages, double quotes signify a string, and I believe it is wise to adapt that into your coding as well.
http://slitherio.online/

iocoder

@Coder100

Coder100

lol thx @ridark

iocoder

@Coder100 i forgot

xD

Coder100
iocoder

cool!
i will try to do these suggestions! after i finish thinking about how stupid i am for using var instead of const and using tabs instead of 2 spaces :{

Edit: i use semis in python
@Coder100

Coder100

LOL @ridark

xxpertHacker

Imho, this is gross:

This is better:

And this is even worse:

You know what, I think even ESLint has recommended this for the last decade:

Coder100

it throws an exception? did not know that lol
and yeah that first one is @xxpertHacker

xxpertHacker

@Coder100 Yeah, just like this does:

Like, what are you doing with your life if you reassign a const like that, your entire script should crash.

CodeLongAndPros

Tabs > spaces
8 wide < 2 wide

Coder100
Coder100

i do use tabs for c++ @CodeLongAndPros

CodeLongAndPros

@Coder100 If you need more than 3 levels of indentation you should refactor anyways

programmeruser

@CodeLongAndPros why would you use spaces? Different editors interpret spaces the same but tabs differently. The only languages I know that care about whitespacfe are Python and Makefile. (also, are you still posting on your blog at https://codelongandprosper90.github.io/?)

Coder100
Coder100

wait no
not for c# smh @CodeLongAndPros

Coder100

@CodeLongAndPros

firefish

@Coder100 Why you always use arrow functions:
The function keyword hoists, so don't use that unless in conjunction with let or use strict;,
and scoping is mucked up in functions. Normal function use this in the scope of the caller, however arrow functions use this in the scope of the callee, a.k.a the sane way.

fuzzyastrocat

@firefish I don't think it's always 100% sane though. I mean, put yourself in the shoes of a newbie JS programmer. What do you expect this to return:

It seems like that should return 1, but no, it returns undefined since there's no global prop. However using a function() { return this.prop; } will return 1 as expected, so I would argue that sometimes arrow functions can be more confusing.

alexz6359

When i look at this. Uhhh I dont understand anything. lol

Coder100
EIG520

I'm pretty sure it's better to use tabs because it requires less data-space.

Coder100

yes, but usually it won't matter because if you were to go to production, your files would ideally be minimized @EIG520

Baconman321

Ur so lucky! My tutorials barely get recognition, and I've done a few on things like the file reader api for JavaScript, service workers, and even a PHP tutorial (which I think I'm going to heavily improve). The most upvotes I got was 7 (might have changed, but eh... I doubt it). ;(

Oh and also, you forgot the importance of comments...

potatojs

@Baconman321 you don't have 10.000 cycles lol

Baconman321

@potatojs Doesn't matter. A 0 cycle person could make a tutorial better than a person with 100k cycles. It doesn't depend on cycles, it depends on skill.

potatojs

@Baconman321 lol i didn't mean that your tutorials are bad, i'm sure they are good enough, but when people see a guy with 100k cycles they upvote immediately :)

Baconman321

@potatojs Sadly...

JBloves27

Nice tutorial!

programmeruser

These can be prefixed with let if you are going to change them. const isn't only for the interpreter, it is also for programmers.

I always default to const and never use let with objects or arrays...

Coder100
Coder100

why not use let for objects and arrays? @programmeruser

programmeruser

@Coder100 no need

Coder100

@programmeruser hmm any reason?