JavaScript Code Style
h
Coder100 (12881)

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.

console.log("hey :smirk:"); // <-- good!
console.log("hey :smirk:") // <-- avoid!

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.

console.log("Let's go outside!");  // <-- good!
console.log('Let\'s go outside!') // <-- avoid!

However, the exception is when you require double quotes:

console.log("\"That's what she said\""); // <-- avoid!
console.log('"I am Coder100"'); // <-- good!
console.log('"That\'s what she said"'); // <-- edge case
console.log(`"That's what she said"`); // <-- good!

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.

function hi() {
  return 5; // <-- good!
}

function hi() {
	return 5; // <-- avoid!
}

Resolving Paths

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

const path = require("path");

path.join(__dirname, "./index.html"); // <-- good!
__dirname + "/index.html"; // <-- avoid!

Destructuring

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

const {log} = console; // <-- avoid!
const { log } = console; // <-- good!
const { log, debug, dir, table, error, warn } = console; // <-- good!
const { log,
        debug,
        dir,
        table,
        error,
        warn } = console; // <-- consider using no wrap (avoid)

Spacing

This code snippet will tell you everything.

if (true) {
  // this is what we want
} else {
  console.log("POG UR COMPUTER IS BROKE");
}

function poggers(a) {
  return 5;
}

let myArr = [1, 2, 3];
myArr.push(10);

poggers(10);

Arrow functions

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

const bad = () => console.log("bad"); // <-- avoid!

hi();

function hi() { // <-- good!
  console.log("goodbye");
}

[1, 2, 3].map(n => n ** 2); // <-- good!
[1, 2, 3].map(function square(n) {
  return n ** 2;
}); // <-- uh ew (avoid)

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

const x = {
  key: "value",
  func: () => this.key // good!
};
x.func(); // => undefined

const y = {
  key: "value",
  func: function () { return this.key; } // good!
};
y.func(); // => "value"

Function Definition

I normally call functions before defining them,

a();

function a() {
  console.log("hi");
}

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

for (let i = 0; i < 10; i++) {
  function a() { return i; }
  console.log(a);
}

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.

const a = 5; // <-- good!
const b = 10; // <-- good!
let g = 10; // <-- good!
g++;

let j = 3; // <-- avoid!

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.

const a = {
  b: 6
};

a.b = 6; // <-- avoid!

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

const a = Object.freeze({
  b: 6
});

a.b = 10; // <-- will silently fail

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.

let a = { b: 6 };
a.b = 10; // <-- good!
a[3] = 10; // <-- good!
a["b"] = 10; // <-- bad!

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

You are viewing a single comment. View All
fuzzyastrocat (1473)

@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.