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 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. var To keep confusion to a minimum, declarations should happen before they are used for the first time. var Bad example: x = ; { alert(x); (something) { x = ; } } fun(); var 1 ( ) function fun // Noncompliant as x is declared later in the same scope if var 42 // Declaration in function scope (not block scope!) shadows global variable // Unexpectedly alerts "undefined" instead of "1" Good example: x = ; { print(x); (something) { x = ; } } fun(); var 1 ( ) function fun if 42 // Print "1" 2. Variables should be declared with "let" or "const" ECMAScript 2015 introduced the and keywords for block-scope variable declaration. Using const creates a read-only (constant) variable. let const The distinction between the variable types created by 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. var 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 to , and you should be aware that they raise SyntaxErrors in pre-ECMAScript 2015 environments. var let This rule raises an issue when is used instead of or . var const let Bad example: color = ; size = ; var "blue" var 4 Good example: color = ; size = ; const "blue" let 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: .foo = ; .log( .foo); { .foo = ; } MyObj.func1 = { ( .foo == ) { } } this 1 // Noncompliant console this // Noncompliant ( ) function MyObj this 1 // Compliant ( ) function if this 1 // Compliant // ... Good example: foo = ; .log(foo); { .foo = ; } MyObj.func1 = { ( .foo == ) { } } 1 console ( ) function MyObj this 1 ( ) function if this 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: myVar = ; { } var 42 // Noncompliant ( ) function myFunc // Noncompliant Good example: .myVar = ; .myFunc = { }; window 42 window ( ) function or myVar = ; myFunc = { } let 42 let ( ) function or ( { myVar = ; { } })(); // IIFE ( ) function var 42 ( ) function myFunc 5. "undefined" should not be assigned 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. undefined Bad example: myObject = {}; myObject.fname = ; (myObject.lname == ) { } (myObject.fname == ) { } var // ... undefined // Noncompliant // ... if undefined // property not yet created if undefined // no real way of knowing the true state of myObject.fname Good example: myObject = {}; myObject.fname = ; (myObject.lname == ) { } (myObject.fname == ) { } var // ... null // ... if undefined // property not yet created if undefined // no real way of knowing the true state of myObject.fname 6. "NaN" should not be used in comparisons is not equal to anything, even itself. Testing for equality or inequality against will yield predictable results, but probably not the ones you want. NaN NaN Instead, the best way to see whether a variable is equal to 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 NaN Bad example: a = ; (a === ) { .log( ); } (a !== ) { .log( ); } var NaN if NaN // Noncompliant; always false console "a is not a number" // this is dead code if NaN // Noncompliant; always true console "a is not NaN" // this statement is not necessarily true Good example: ( .isNaN(a)) { .log( ); } (! .isNaN(a)) { .log( ); } if Number console "a is not a number" if Number console "a is not NaN" 7. Jump statements should not occur in "finally" blocks Using return, break, throw, and continue from a block overwrites similar statements from the suspended try and catch blocks. finally This rule raises an issue when a jump statement (break, continue, return and throw) would force control flow to leave a block. finally Bad example: { { ; } (err) { ; } { ; } } ( ) function foo try return 1 // We expect 1 to be returned catch 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: { { ; } (err) { ; } } ( ) function foo try return 1 // We expect 1 to be returned catch 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: { .reject( ); } { { runPromise(); } (e) { .log( , e); } } ( ) function runPromise return Promise "rejection reason" ( ) function foo try // Noncompliant, the catch clause of the 'try' will not be executed for the code inside promise catch console "Failed to run promise" Good example: { runPromise().catch( .log( , e)); } { { runPromise(); } (e) { .log( , e); } } ( ) function foo => e console "Failed to run promise" // or async ( ) function foo try await catch console "Failed to run promise" 9. "await" should not be used redundantly An async function always wraps the return value in a Promise. Using return is therefore redundant. Bad example: await { } { foo(); } async ( ) function foo // ... async ( ) function bar // ... return await // Noncompliant Good example: { } { foo(); } async ( ) function foo // ... async ( ) function bar // ... return 10. "void" should not be used The 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 ( { ... }()); void ( ) function Good example: ( { ... }()); ( ) function 11. Shorthand promises should be used When a Promise needs to only " " or " ", 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: resolve reject fulfilledPromise = ( resolve( )); rejectedPromise = ( { reject( ); }); let new Promise => resolve 42 let new Promise ( ) function resolve, reject 'fail' Good example: fulfilledPromise = .resolve( ); rejectedPromise = .reject( ); let Promise 42 let Promise '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! Special thanks to SonarQube and their rules - https://www.sonarqube.org/ More tips: Top 25 C# Programming Tips