Hi everyone! There is a lot of information about different JS best practices. About various life hacks and features in this language. I want to tell you about equally useful, but less popular tips for working with this JavaScript.

1. Variables declared with “var” should be declared before they are used

Variables declared with var have the special property that regardless of where they’re declared in a function they “float” to the top of the function and are available for use even before they’re declared. That makes scoping confusing, especially for new coders.

To keep confusion to a minimum, var declarations should happen before they are used for the first time.

Bad example:

var x = 1;

function fun(){
alert(x); // Noncompliant as x is declared later in the same scope
if(something) {
var x = 42; // Declaration in function scope (not block scope!) shadows global variable
}
}

fun(); // Unexpectedly alerts “undefined” instead of “1”

Good example:

var x = 1;

function fun() {
print(x);
if (something) {
x = 42;
}
}

fun(); // Print “1”

2. Variables should be declared with “let” or “const”

ECMAScript 2015 introduced the let and const keywords for block-scope variable declaration. Using const creates a read-only (constant) variable.

The distinction between the variable types created by var and by let is significant, and a switch to let will help alleviate many of the variable scope issues which have caused confusion in the past.

Because these new keywords create more precise variable types, they are preferred in environments that support ECMAScript 2015. However, some refactoring may be required by the switch from var to let, and you should be aware that they raise SyntaxErrors in pre-ECMAScript 2015 environments.

This rule raises an issue when var is used instead of const or let.

Bad example:

var color = “blue”;
var size = 4;

Good example:

const color = “blue”;
let size = 4;

3. The global “this” object should not be used

When the keyword this is used outside of an object, it refers to the global this object, which is the same thing as the window object in a standard web page. Such uses could be confusing to maintainers. Instead, simply drop the this, or replace it with window; it will have the same effect and be more readable.

Bad example:

this.foo = 1; // Noncompliant
console.log(this.foo); // Noncompliant

function MyObj() {
this.foo = 1; // Compliant
}

MyObj.func1 = function() {
if (this.foo == 1) { // Compliant
// …
}
}

Good example:

foo = 1;
console.log(foo);

function MyObj() {
this.foo = 1;
}

MyObj.func1 = function() {
if (this.foo == 1) {
// …
}
}

4. Variables and functions should not be declared in the global scope

Any variable or function declared in the global scope implicitly becomes attached to the global object (the window object in a browser environment). To make it explicit this variable or function should be a property of window. When it is meant to be used just locally, it should be declared with the const or let keywords (since ECMAScript 2015) or within an Immediately-Invoked Function Expression (IIFE).

This rule should not be activated when modules are used.

Bad example:

var myVar = 42; // Noncompliant
function myFunc() { } // Noncompliant

Good example:

window.myVar = 42;
window.myFunc = function() { };
or

let myVar = 42;
let myFunc = function() { }
or

// IIFE
(function() {
var myVar = 42;
function myFunc() { }
})();

5. “undefined” should not be assigned

“undefined” is the value you get for variables and properties which have not yet been created. Use the same value to reset an existing variable and you lose the ability to distinguish between a variable that exists but has no value and a variable that does not yet exist. Instead, null should be used, allowing you to tell the difference between a property that has been reset and one that was never created.

Bad example:

var myObject = {};

// …
myObject.fname = undefined; // Noncompliant
// …

if (myObject.lname == undefined) {
// property not yet created
}
if (myObject.fname == undefined) {
// no real way of knowing the true state of myObject.fname
}

Good example:

var myObject = {};

// …
myObject.fname = null;
// …

if (myObject.lname == undefined) {
// property not yet created
}
if (myObject.fname == undefined) {
// no real way of knowing the true state of myObject.fname
}

6. “NaN” should not be used in comparisons

NaN is not equal to anything, even itself. Testing for equality or inequality against NaN will yield predictable results, but probably not the ones you want.

Instead, the best way to see whether a variable is equal to NaN is to use Number.isNaN(), since ES2015, or (perhaps counter-intuitively) to compare it to itself. Since NaN !== NaN, when a !== a, you know it must equal NaN.

Bad example:

var a = NaN;

if (a === NaN) { // Noncompliant; always false
console.log(“a is not a number”); // this is dead code
}
if (a !== NaN) { // Noncompliant; always true
console.log(“a is not NaN”); // this statement is not necessarily true
}

Good example:

if (Number.isNaN(a)) {
console.log(“a is not a number”);
}
if (!Number.isNaN(a)) {
console.log(“a is not NaN”);
}

7. Jump statements should not occur in “finally” blocks

Using return, break, throw, and continue from a finally block overwrites similar statements from the suspended try and catch blocks.

This rule raises an issue when a jump statement (break, continue, return and throw) would force control flow to leave a finally block.

Bad example:

function foo() {
try {
return 1; // We expect 1 to be returned
} catch(err) {
return 2; // Or 2 in cases of error
} finally {
return 3; // Noncompliant: 3 is returned before 1, or 2, which we did not expect
}
}

Good example:

function foo() {
try {
return 1; // We expect 1 to be returned
} catch(err) {
return 2; // Or 2 in cases of error
}
}

8. Promise rejections should not be caught by ‘try’ block

An exception (including reject) thrown by a promise will not be caught by a nesting try block, due to the asynchronous nature of execution.

Instead, use catch method of Promise or wrap it inside await expression.

This rule reports try-catch statements containing nothing else but call(s) to a function returning a Promise (thus it’s less likely that catch is intended to catch something else than Promise rejection).

Bad example:

function runPromise() {
return Promise.reject(“rejection reason”);
}

function foo() {
try { // Noncompliant, the catch clause of the ‘try’ will not be executed for the code inside promise
runPromise();
} catch (e) {
console.log(“Failed to run promise”, e);
}
}

Good example:

function foo() {
runPromise().catch(e => console.log(“Failed to run promise”, e));
}

// or
async function foo() {
try {
await runPromise();
} catch (e) {
console.log(“Failed to run promise”, e);
}
}

9. “await” should not be used redundantly

An async function always wraps the return value in a Promise. Using return await is therefore redundant.

Bad example:

async function foo() {
// …
}

async function bar() {
// …
return await foo(); // Noncompliant
}

Good example:

async function foo() {
// …
}

async function bar() {
// …
return foo();
}

10. “void” should not be used

The void operator evaluates its argument and unconditionally returns undefined. It can be useful in pre-ECMAScript 5 environments, where undefined could be reassigned, but generally, its use makes code harder to understand.

Bad example:

void (function() {

}());

Good example:

(function() {

}());

11. Shorthand promises should be used

When a Promise needs to only “resolve” or “reject”, it’s more efficient and readable to use the methods specially created for such use cases: Promise.resolve(value) and Promise.reject(error).

Bad example:

let fulfilledPromise = new Promise(resolve => resolve(42));
let rejectedPromise = new Promise(function(resolve, reject) {
reject(‘fail’);
});

Good example:

let fulfilledPromise = Promise.resolve(42);
let rejectedPromise = Promise.reject(‘fail’);

12. “future reserved words” should not be used as identifiers

The following words may be used as keywords in future evolutions of the language, so using them as identifiers should be avoided to allow an easier adoption of those potential future versions:

await
class
const
enum
export
extends
implements
import
interface
let
package
private
protected
public
static
super
yield

Use of these words as identifiers would produce an error in JavaScript strict mode code.

P.S. Thanks for reading! More tips coming soon!

This article is republished from hackernoon.com

Previous Application Modernization Isn’t Easy. But We Can Make It Easier.
Next 7 Bash Tutorials To Enhance Your Command Line Skills In 2021