Var Declaration


When you declare a variable with var, the variable is **hoisted** to the top of its scope, which means it can be accessed and used before it is declared. This is known as variable hoisting. For example:

//Output: undefined
console.log(x);
var x = 5;

In the example above, the variable x is declared and assigned a value of 5 on the second line. However, when we try to log x to the console on the first line, it outputs undefined instead of throwing an error.

Here is an example using the let declaration:

//ReferenceError: Cannot access 'x' before initialization
console.log(x);
let x = 5;

In the example above, the result of trying to access x is going to throw an error.

This is because the var x declaration is hoisted to the top of its scope, which in this case is the global scope.

Unlike let and const, var variables have function scope, which means they are only accessible within the function in which they are declared. If a var variable is declared outside of any function, it has global scope and can be accessed from anywhere in the code.

One thing to be aware of when using var variables is that they can be redeclared within the same scope without throwing an error. For example:

var x = 5;
var x = 10;
console.log(x); // Output: 10

In the example above, the variable x is declared and assigned a value of 5. Then, on the second line, x is declared again and assigned a new value of 10. The console.log(x) statement on the third line outputs 10, because x now holds that value.

Differences between var and let

Feature var let
Scope Function scope Block scope
Hoisting Yes, variable declarations are hoisted No, variable declarations are not hoisted
Initialization Initialized with undefined when hoisted Not initialized, using the variable before declaration causes a ReferenceError
Global Object When declared globally, attached to the global object (window in browsers) When declared globally, not attached to the global object
Re-declaration Allows re-declaration of the same variable within the same scope Disallows re-declaration of the same variable within the same scope

By using let instead of var, you can create block-scoped variables, avoid hoisting-related issues, and prevent accidentally re-declaring variables, resulting in more predictable and maintainable code.

Overall, var variables are still used in many existing codebases, but they have some limitations and quirks that can make them less preferable than let and const variables in modern JavaScript.

Advance Operators


Ternary Operator

The ternary operator (also called the conditional operator) is a shorthand way of writing an if...else statement. It has the following syntax:

condition ? expressionIfTrue : expressionIfFalse
let age = 18;
let isAdult = age >= 18 ? "Yes" : "No";

console.log(isAdult); // "Yes"

In this example, since the condition age >= 18 is true, the isAdult variable is assigned the value "Yes". If the condition were false, it would be assigned the value "No".

Typeof Operator

The typeof operator returns a string indicating the data type of a given value:

console.log(typeof 42);           // "number"
console.log(typeof "Hello");      // "string"
console.log(typeof true);         // "boolean"
console.log(typeof undefined);    // "undefined"
console.log(typeof {name: "John"}); // "object"

Nullish Coalescing Operator

The nullish coalescing operator (??) returns the right-hand side operand when the left-hand side operand is null or undefined. Otherwise, it returns the left-hand side operand:

let a = null;
let b = "Hello, World!";
let c = a ?? b;

console.log(c); // "Hello, World!"

Optional Chaining Operator

The optional chaining operator (?.) allows you to access properties of an object without throwing an error if the object is null or undefined:

let person = {
  name: "John",
  address: {
    street: "Main St",
    city: "New York",
  },
};

console.log(person.address?.street); // "Main St"
console.log(person.job?.title);      // undefined (no error)

In this example, since person.job is not defined, using the optional chaining operator with person.job?.title returns undefined without throwing an error. If we had used person.job.title without the optional chaining operator, a TypeError would have occurred.

Instanceof Operator

The instanceof operator is used to check if an object is an instance of a particular class or constructor:

class Car {
  constructor(make, model) {
    this.make = make;
    this.model = model;
  }
}

let myCar = new Car("Toyota", "Camry");

console.log(myCar instanceof Car); // true
console.log(myCar instanceof Object); // true

In this example, myCar is an instance of both the Car class and the Object class, so both checks return true.

In Operator

The in operator is used to check if an object has a specified property:

let person = {
  name: "John",
  age: 30,
};

console.log("name" in person); // true
console.log("address" in person); // false

In this example, the person object has a name property, so ("name" in person) returns true. It does not have an address property, so ("address" in person) returns false.

Spread Operator

The spread operator (...) is used to expand elements of an iterable object (like arrays or strings) into individual elements. It can be particularly useful in copying arrays, concatenating arrays, and passing elements of an array as function arguments:

Copying Arrays

let originalArray = [1, 2, 3];
let copiedArray = [...originalArray];

console.log(copiedArray); // [1, 2, 3]

Concatenating Arrays

let array1 = [1, 2, 3];
let array2 = [4, 5, 6];
let concatenatedArray = [...array1, ...array2];

console.log(concatenatedArray); // [1, 2, 3, 4, 5, 6]

Passing Array Elements as Function Arguments

function sum(a, b, c) {
  return a + b + c;
}

let numbers = [1, 2, 3];
console.log(sum(...numbers)); // 6

Rest Operator

The rest operator (...) can also be used in a different context, to collect the remaining elements of an iterable into an array. This is particularly useful when working with functions that accept a variable number of arguments:

function sum(...numbers) {
  let total = 0;
  for (let number of numbers) {
    total += number;
  }
  return total;
}

console.log(sum(1, 2, 3)); // 6
console.log(sum(1, 2, 3, 4, 5)); // 15

In this example, the sum function can accept any number of arguments, which are then collected into the numbers array using the rest operator.

The Global Object in JavaScript


The global object in JavaScript is a top-level container for variables and functions that are accessible throughout the entire application. It provides built-in properties and functions and serves as a container for user-defined global variables and functions.

Key Features

  1. Built-in properties and functions: The global object includes essential built-in properties and functions, such as constructors (e.g., Object, Array, Date), global functions (e.g., parseInt(), parseFloat(), isNaN()), and global properties (e.g., undefined, NaN, Infinity).
  2. User-defined global variables and functions: When you declare a global variable or function, it becomes a property of the global object. However, this does not apply to module systems (e.g., ECMAScript modules or CommonJS).98
  3. Access to global variables and functions: The global object allows you to access global variables and functions from any part of your code, including within functions.
  4. this value in the global scope: In the global scope, the this keyword refers to the global object (window in browsers and global in Node.js). In ECMAScript modules, this is undefined in the global scope.

Environments

Best Practices

Example

// Built-in property
console.log(Math.PI); // Output: 3.141592653589793

// User-defined global variable
var globalVar = 'I am global!';
console.log(window.globalVar); // Output: 'I am global!' (in a browser environment)

By understanding the global object, you can take advantage of built-in properties and functions, as well as manage your global variables and functions effectively.

[](data:image/svg+xml,%3csvg%20xmlns=%27http://www.w3.org/2000/svg%27%20version=%271.1%27%20width=%2730%27%20height=%2730%27/%3e)

Additional Considerations

When working with the global object in JavaScript, it is essential to consider the following aspects to ensure your code is clean, maintainable, and efficient:

Avoid Polluting the Global Namespace

Adding too many global variables or functions can lead to naming conflicts and make your code harder to understand and maintain. To avoid polluting the global namespace:

Use Global Object as a Fallback

Sometimes you may need to use global variables or functions as a fallback when a locally scoped variable is not available. In such cases, you can use the global object to check for the existence of a variable or function before creating it.

// Check if a global variable exists, if not, create it
if (!window.myGlobalVar) {
  window.myGlobalVar = 'I am a global fallback!';
}

Be Aware of Platform Differences

While the global object is window in browser environments and global in Node.js environments, other JavaScript environments might use different global objects. Be aware of the platform you are working on and adjust your code accordingly.

Use Strict Mode

Strict mode is a feature in JavaScript that helps you write safer and more robust code by enforcing stricter rules and disabling some error-prone features. When using strict mode, the global object behaves differently:

To enable strict mode, add the following line at the beginning of your script or function:

'use strict';

By following these additional considerations, you can work with the global object more effectively and ensure your JavaScript code is cleaner, more maintainable, and less prone to errors.

JavaScript Hoisting

Hoisting is a concept in JavaScript where variable and function declarations are moved to the top of their containing scope during the compilation phase, before the code is executed. This can lead to some unexpected behavior, especially for developers who are new to JavaScript.

How Hoisting Works

In JavaScript, there are two main types of declarations: var and function. When the JavaScript engine compiles your code, it moves these declarations to the top of their scope. This is known as hoisting. Let's look at an example:

console.log(message);
var message = "Hello, World!";

You might expect this code to output undefined, but because of hoisting, it actually works like this:

var message;
console.log(message);
message = "Hello, World!";

The var message declaration is hoisted to the top of the scope, while the assignment remains in place. This is why the output is undefined and not an error.

Function Hoisting