Advanced JavaScript Series - Part 3: Weird JS behavior, Strict Mode and Hoisting

Weird JS Behavior

Code-

Output-

50
50

In the code sample, we didn't even explicitly declare the variable but we are able to use without any error and it is available in global scope

Explanation-

  • Older versions of JS allowed us to create variables without explicitly declaring them using the var, let or the const keyword.
  • There are a lot of downfalls to this, some of them being-

Downfalls-

  • JS creates these variables in global scope by default thus anyone can access them from outside the function and change them.
  • You can mistype a variable name and JS won't even give an error, instead it will create a new variable in the global scope because of this behavior.

Solution: Strict Mode

Introduction-

  • The "use strict" directive was new in ECMAScript version 5 indicating use of strict mode while running the code.
  • It is supported by all the modern browsers and since it is only a string, even older versions that don't understand it won't throw any error.
  • It prevents all the bad code practices in previous JS versions from turning into actual errors.
  • If declared at the beginning of a script, it has global scope whereas if it is used inside the function then it's scope is only for that block/block scope.

Declaration example-

"use strict";
x = 3.14;  // this will cause error

Issues that "use strict" fixes-

  1. If you mistakenly mistype a variable, if ran in strict mode, it will throw an error instead of creating a new global variable.
  2. It prevents us from assigning values to non-writable properties by throwing an error. This wasn't the same in previous versions.
  3. Keywords reserved for future JavaScript versions can not be used as variable names in strict mode.
  4. Prevents us from duplicating parameter names.
  5. Prevents us from writing to a read-only properties.
  6. Prevents us from writing to a get-only property.
"use strict";
const obj = {get x() {return 0} };

obj.x = 3.14;            // This will cause an error

7.Prevents us from deleting an undeletable property.

"use strict";
delete Object.prototype; // This will cause an error

8.Prevents us from using Octal numerical literals and Octal escape characters. Example-

"use strict";
let x = 010; // gives error
let x = "\010"; // gives error
  • Check this article for all the things that are not allowed in "use strict".

Note- The "use strict" directive is only recognized at the beginning of a script or a function.

Hoisting-

  • Hoisting is JavaScript's default behavior of moving all the declarations at the top of the scope before code execution.
  • It could be variable declarations or function declarations or even class declarations. Hoisting Credits-tutorialsteacher

Example of variable hoisting-

Code-

x = 5 // doesn't give any error because of hoisting
console.log(x)

var x // this gets hoisted to the top of the scope

Output-

5

Example of function hoisting-

Code-

console.log(hello()) // doesn't give any error because of hoisting

function hello(){ // this gets hoisted to the top of the scope
    return "hello world"
}

Output-

"hello world"
  • The let and const keywords are hoisted but not initialized meaning that the block of code is aware of the variable but cannot use it until it's been declared, thus they give error.

Code-

x = 5
console.log(x)

let x

Output-

ReferenceError: Cannot access 'x' before initialization

Code-

x = 5
console.log(x)

const x

Output-

SyntaxError: Missing initializer in const declaration
  • All JavaScript declarations are hoisted but not for initialization. Initialization in variables using var keyword are partially hoisted but those using let or const keyword are not hoisted at all and give error.

  • Partial hoisting means that the JS engine before running the code line by line already knows that the variable exists and has some memory allocated (because of hoisting) but the value for it hasn't been set/ stored yet (it gets set when we actually reach that line of code) thus undefined is returned. This partial hoisting happens in case of variable initialization using var keyword.
    Partial Hoisting
    Credits- Sabih Rehman

Example 1

Code-

console.log(x)

var x = 5 // this is initialization, not a declaration

Output-

undefined

This code does not work because initializations are not hoisted. It returns undefined because we have used var here that leads to partial hoisting as discussed above.

Example 2

Code-

console.log(x)

let x = 5 // this is initialization, not a declaration

Output-

Uncaught ReferenceError: Cannot access 'x' before initialization"

This is because variable initialization using let or const don't get hoisted.

Appendix-

References-

All codes implemented using JS Fiddle

24