DEV Community

Cover image for JavaScript Best Practices for Beginners
Syed Afroz Pasha
Syed Afroz Pasha

Posted on • Originally published at Medium

JavaScript Best Practices for Beginners

Let us quickly discuss some of the best practices which you can follow while working with JavaScript. I have covered some of the basic stuff which we will be using often in our day-to-day programming.

Letโ€™s get started.

Always define variables using let or const

By defining variables using let or const, we can avoid problems such as

  • Pollution of global variables and namespaces: Letโ€™s say your application uses a global variable title. In some other part of your code, you have defined a variable title (without let or const) again, but this variable is specific to that function and it is nowhere related to the global variable title. Then there might be a chance this title variable might mutate (change) the global value.

Pollution of global variables

  • If we define the variables using let or const, the variable will be blocked scoped meaning itโ€™s only available to that block of code. Hence it will not be able to change the global variable.

Remediation for pollution of global variables

  • Exposing sensitive data: Letโ€™s say you are storing the API key in a global variable (which you defined without let or const), then this API key will be stored in the global object (window) and can be easily accessed by anyone visiting your site.

Sensitive data can be accessed from the global object (window)

  • Again if we define the variables using let or const, the variable will be blocked scoped and it will not be exposed to the global object (window).

Always define conditions correctly

  • If you want to check a variable for falsy values (undefined, null, an empty string), simply use NOT operator (!) instead of checking each and every falsy value.

Checking falsy values

  • If you want to check if a key/value is present in an object. You can safely check one by one if that key/value exists using AND operator (&&).

Checking if object key/value exists or not

  • You can also use optional chaining to check whether a key/value is present in an object or not.

Optional Chaining

Semicolon

Before we dive deep, here is an activity for you. Can you guess what will be the output of the below function?

What will be the output of the console?

Answer: The output will be undefined ๐Ÿ˜ฒ. But how?, This is because of automatic semicolon insertion by JavaScript Engine while parsing the code. If the code is not formatted correctly like in the above example, JavaScript Engine will add a semicolon(;) to the end of the return statement (return;) and it thinks that no value is returned. So returns a value as undefined.

Automatic Semicolon Insertion (ASI): At the time of parsing the code, JavaScript Engine automatically inserts a semicolon at the end of each token. This sometimes may cause unexpected behavior of code. You can read more about it here

Automatic Semicolon Insertion

It is also recommended to add a semicolon at the end of each statement of the code to avoid ASI problems.

Brackets

People from different programming language backgrounds tend to start the braces in the next line. But in JavaScript, this can cause unexpected behavior of the code.

  • Never start the curly braces ({}) in the next line. Because of ASI, your code may behave unexpectedly.

BAD Brackets

  • Always start the curly braces just after the end of the statement (in the same line).

GOOD bracket

We can avoid these problems, by formatting the code using Prettier or any other formatting tools/libraries.

Template Literals

Template literal is used to define a string value. Template literals are enclosed by the backtick and dynamic values/placeholder can be passed using the dollar symbol ${dynamicValue}.

Example for Template Literal

Below are some of the use cases of template literals.

  • Template literals can be used to define dynamic HTML content.

Defining dynamic HTML content using template literals

  • Template literals can be used to define database queries

Defining DB queries using template literals

  • Template literals can be used to define dynamic shorts URLs (single line).

Defining short URLs using template literals

  • Do not use template literals to define long URLs with multi-lines. As APIs do not support the multi-line URLs. There are many workarounds available to handle multiple parameters in a single line, but we are not going to discuss all of that here.

Avoid template literals for long multi-line URLs

We can avoid most of the problems discussed in this article by using linters and code formatters. Here are some of the popular linters and code formatters.
Linters: ESLint , JSLint
Code formatters: Prettier

Thatโ€™s all I have for today. Hope you enjoyed it. ๐Ÿ˜‰

You also check out my article on Naming variables and functions in JavaScript.

Thank you for stopping by. If you like the content do support me and follow me for more content like this.

Connect with me on LinkedIn, Twitter, and GitHub.

Discussion (6)

Collapse
jayjeckel profile image
Jay Jeckel

Slight terminology correction:
{ } are Braces or Curly Brackets
[ ] are Brackets or Square Brackets
( ) are Parentheses or Round Brackets
< > are Chevrons or Angle Brackets

Also, as someone who is not a javascript dev, I have to ask, what problems does the language have with the proper formatting of braces on their own lines?

Collapse
syedafrozpasha profile image
Syed Afroz Pasha Author

In JavaScript, it is recommended to start the braces in the same line, because of the automatic semicolon insertion. When a code gets parsed by JavaScript Engine, it will automatically insert a semicolon at the end of the line where tokens (such as if, else, etc.) are present. Because of this your code might not work as expected. To understand it better, execute this code snippet - one with braces on the next line and another one with braces on the same line.

Nowadays, most of the modern browsers can handle it gracefully. But again it is preferred to define braces in the same line.

Collapse
jayjeckel profile image
Jay Jeckel

Looking at the ECMAScript standard section 11.9, I think you are misunderstanding automatic semicolon insertion. ASI is only going to insert semicolons if there is ambiguity in how to parse the code.

In other words, to insert a semicolon, the parser first has to find a token that it doesn't understand or isn't certain about, what the spec calls an "offending token". In a well formatted if-else statement like the example below there are no offending tokens and no semicolons will be inserted.

if (someBoolean)
{
}
else
{
}
Enter fullscreen mode Exit fullscreen mode

Same thing for your examples in the article. There are no offending tokens in these examples, so the parser has no reason to insert semicolons.

if (!userName)
{
}

for (let i = 0; i < n; i++)
{
}

function getUser()
{
}
Enter fullscreen mode Exit fullscreen mode

If the parser did include semicolons as you suggest, it would break the code. The examples below would print "do not print", even though the condition is false, because the if is now an empty and its block of code is just regular inline code in the file. Same for the loop, it now does effectively nothing and is separated from its block, so "loop" is printed once and not 10 times. Where as the semicolon in the function is an error, so the function isn't called and nothing is printed.

if (false);
{
    console.log('do not print');
}

for (let i = 0; i < 10; i++);
{
    console.log('loop');
}

function getUser();
{
    console.log('broken function');
}

getUser();
Enter fullscreen mode Exit fullscreen mode

The ASI issue is a quirk that arises when splitting statements and expressions across multiple lines and has nothing directly to do with braces or general conventions of putting them on the same line or a new line.

I'll close by including the practical advice from the EMCA spec itself:

The resulting practical advice to ECMAScript programmers is:

  • A postfix ++ or -- operator should appear on the same line as its operand.
  • An Expression in a return or throw statement or an AssignmentExpression in a yield expression should start on the same line as the return, throw, or yield token.
  • A LabelIdentifier in a break or continue statement should be on the same line as the break or continue token.
Collapse
lukeshiru profile image
LUKESHIRU

The title says "Best practices", and some of them aren't good:

  • We shouldn't use global variables at all. The issue is not to create a global variable and then change that, the issue is just to have a global in the first place.
  • Using falsy values is not a "best practice", you should check for specific values to make the intention in your code clear. If writing a chain of && with !== is too much for you, you can always do something like [undefined, null, ""].includes(sessionId), for example.
  • For the optional chaining operator (?.) you should use it with the nullish coalescing operator (??). It would be something like const { country = "default value" } = user?.address ?? {}, or const country = user?.address?.country ?? "default value".
  • The URL string can be written like this:
const url = `${process.env.API_HOST}/v1/search?${new URLSearchParams({
    query: searchTerm,
    filter,
    sort
})}`
Enter fullscreen mode Exit fullscreen mode

Lastly, a tip, try using code blocks like the one I just used in your posts, it makes your code snippets easier to read on mobile, more accessible for folks that can't read the screen, and easier for you to update later.

Cheers!

Collapse
syedafrozpasha profile image
Syed Afroz Pasha Author • Edited

Firstly, Thank you for taking the time to read my article.

  • I agree with you we shouldn't use global variables at all. But there might be some scenarios where we might require to use global variables depending on projects.

  • Well, different developers use different styles for writing a piece of code. In my case, I would prefer to check falsy values by using NOT operator (!), which is very much cleaner and does the job.

  • Agree with you, it is preferred to use optional chaining operator (?.) with the coalescing operator (?? or ||). Again it depends on the developer, how he/she want to use it. I would do something like this.

const county = user?.address?.country || 'Default Value';
Enter fullscreen mode Exit fullscreen mode
  • Wow, that's an interesting solution ๐Ÿ‘

Let's not forgot that this article is for beginners who have just started learning JavaScript. What I have cover in this article is just the tip of the iceberg ๐Ÿ˜‰

Lastly, Thanks for the tip, I will make sure to add code snippets instead of images in the future.

Cheers! ๐Ÿ‘

Collapse
ayabouchiha profile image
Aya Bouchiha

Amazing article, I really appreciate this great work.