- The var statement declares a function-scoped or globally-scoped variable, optionally initializing it to a value.
- Global variables are
- declared outside of a function
- declared with a window object.
- declared as a variable without using var(will not work if "use strict" used).
- Functional variables are
- declared inside a function.
- Accessed within the function.
- var allows variables to be hoisted and initialized with undefined.
- var allows re-declaring a variable.
"use strict"
var globalVar = 5;
console.log("globalVar", globalVar);
function test(){
var funcVar =5;
console.log("globalVar", globalVar);
console.log("funcVar", funcVar);
}
test();
console.log("globalVar", globalVar);
// console.log("funcVar", funcVar); //ReferenceError: funcVar is not defined
- let and const are block scoped.
- let and const allow to hoist variables and through Reference Error if accessed.
- let and const do not allow re-declaring a variable
// Block Scope :
if (true) {
var a = 10;
let b = 20;
const c = 30;
}
console.log(a); // 10
// console.log(b); //ReferenceError: b is not defined
// console.log(c); //ReferenceError: c is not defined
//hoisting:
console.log(x); // undefined
var x = 5;
// converted into
// var x;
// console.log(x); // undefined
// x = 5;
console.log(y); // ReferenceError: Cannot access 'y' before initialization
let y = 5;
console.log(z); // ReferenceError: Cannot access 'z' before initialization
const z = 5;
let & const diff
- let - values can be changed.
- const - values cannot be changed.(object properties can be updated).
// difference between let and const
let x = 5;
const a = 10;
x = 100;
a = 100; // Assignment to constant variable.
// const object properties can be updated
const x = {
a:10,
b:5
}
x.c = 15;
- Definition: Lexical scope (also called static scope) is determined by the position of a variable's declaration within the source code. It's resolved at compile time (or when the code is parsed). You can visualize it by looking at the nested structure of functions.
- How it works: When the JavaScript engine encounters a variable, it first looks for the variable in the current scope. If it doesn't find it, it moves outward to the enclosing (parent) scope, and then to the parent's parent scope, and so on, until it finds the variable or reaches the global scope.
- Example:
function outerFunction() {
let outerVar = "I'm from the outer function";
function innerFunction() {
let innerVar = "I'm from the inner function";
console.log(innerVar); // Output: I'm from the inner function
console.log(outerVar); // Output: I'm from the outer function (lexical scoping)
}
innerFunction();
console.log(outerVar); // Output: I'm from the outer function
// console.log(innerVar); // Error: innerVar is not defined in the outer function's scope
}
outerFunction();
In this example:
- innerFunction has access to both innerVar (its own variable) and outerVar (from its parent scope, outerFunction). This is lexical scoping.
- outerFunction has access to outerVar but not innerVar. Scope lookup goes outward, not inward.
- If you tried to access innerVar outside of innerFunction, you'd get an error.
- Definition: Variables declared with var have function scope. They are accessible anywhere within the entire function, regardless of where they are declared inside that function.
- Example:
function myFunction() {
var x = 10;
if (true) {
var y = 20;
console.log(x); // Output: 10
}
console.log(y); // Output: 20 (y is still accessible here because of function scope)
}
myFunction();
- Important Note: Function scope with var can lead to unexpected behavior because variables can be accessed even before their declaration (due to hoisting). It's generally recommended to use let and const (block scope) whenever possible to avoid these issues.
- Definition: Variables declared with let and const have block scope. They are only accessible within the block of code (e.g., inside curly braces {}) where they are defined.
- Example:
function myBlockScopeFunction() {
let x = 10;
if (true) {
let y = 20;
const z = 30; // const variables are also block-scoped
console.log(x); // Output: 10
console.log(y); // Output: 20
console.log(z); // Output: 30
}
console.log(x); // Output: 10
// console.log(y); // Error: y is not defined (block scope)
// console.log(z); // Error: z is not defined (block scope)
}
myBlockScopeFunction();
- Benefits of Block Scope: Block scope helps prevent accidental variable overwriting and makes code more predictable and easier to reason about. It's a best practice to use let and const whenever you can.
- Definition: Variables declared outside of any function or block have global scope. They are accessible from anywhere in your code.
- Example:
var globalVar = "I'm global"; // Using var (generally avoid)
let globalLet = "I'm also global (but better)"; // Using let (preferred)
const globalConst = "I'm a global constant";
function myFunction() {
console.log(globalVar); // Output: I'm global
console.log(globalLet); // Output: I'm also global (but better)
console.log(globalConst); // Output: I'm a global constant
}
myFunction();
console.log(globalVar); // Output: I'm global
- Caution: Overuse of global variables can make your code harder to maintain and debug. It's best to minimize their use and keep variables within the smallest scope necessary.
Summary Table:
| Scope Type | Keyword(s) | Accessibility |
|---|---|---|
| Lexical (Static) | N/A | Determined by code structure (nested functions) |
| Function | var | Within the entire function |
| Block | let, const | Within the block (e.g., {}) where defined |
| Global | N/A (outside functions/blocks) | Anywhere in the code |
https://scotch.io/tutorials/understanding-hoisting-in-javascript#toc-undefined-vs-referenceerror
Hoisting is a JavaScript mechanism where variables and function declarations are moved to the top of their scope before code execution.
Variable Definition > Function Declaration > Variable Declaration
- var: Variables declared with var are hoisted to the top of their scope and initialized with undefined.
console.log(x); // Output: undefined
var x = 10;
- let and const: Variables declared with let and const are also hoisted, but they are not initialized.
console.log(y); // Output: ReferenceError: Cannot access 'y' before initialization
let y = 20;
- Function declarations are hoisted to the top of their scope, allowing to call a function before its declaration in the code.
func_decl();
function func_decl() {
console.log("function declaration")
}
- Function expressions are not hoisted.
func_expr(); // ReferenceError: Cannot access 'func_expr' before initialization
let func_expr = function() {
console.log("anonymous function expression")
}
- A function is a JavaScript procedure—a set of statements that performs a task.
- A method is a function that is a property of an object.
- Constructor is a function invoked during creating an class or object.
In JavaScript, the Temporal Dead Zone (TDZ) is the period between the start of a variable's scope and when it is actually declared and initialized.
console.log(y);
let y =5;
console.log(y);
- When you declare a variable with let or const, it is hoisted to the top of its scope. However, unlike var variables which are initialized to undefined, let and const variables are not initialized during hoisting.
- The TDZ is the period where the variable exists in scope but you cannot access it before its declaration. If you try to access a variable within its TDZ, you will get a ReferenceError.
- The TDZ only applies to variables declared with let and const.
- Variables declared with var do not have a TDZ.
- The TDZ helps catch errors early and promotes better coding practices.
reverses truthy value to falsey or vice-versa
let x = 5;
let y = 10;
if(x != y){
console.log("not equal");
}else{
console.log("equal");
}
let z = false;
console.log(z); // false
console.log(!z); // true
console.log(!!z); // false
console.log(!!!z); // true
You can use the logical or operator || in an assignment expression to provide a default value.
var a = b || c;
As per the above expression, variable 'a 'will get the value of 'c' only if 'b' is falsy (if is null, false, undefined, 0, empty string, or NaN), otherwise 'a' will get the value of 'b'.
Template literals helps us to do string interpolation, or to include variables in a string. Template literals, however, preserve whatever spacing you add to them.
const person = { name: 'Tyler', age: 28 };
console.log(`Hi, my name is ${person.name} and I am ${person.age} years old!`);
// 'Hi, my name is Tyler and I am 28 years old!'
var x = 10, y = 20;
[x, y] = [y, x];
console.log(typeof 6) // number
console.log(typeof 6.66) // number
console.log(typeof 6e3) // number
console.log(typeof 6/0) // Infinity
console.log(typeof -6/0) // -Infinity
console.log(typeof 6/"abc") // NaN
console.log(typeof NaN); // number
console.log(typeof Infinity); // number
console.log(typeof -Infinity); // number