- JavaScript Introduction
- JavaScript Where To
- JavaScript Output
- JavaScript Statements
- JavaScript Syntax
- JavaScript Comments
- JavaScript Variables
- JavaScript Let
- JavaScript Const
- JavaScript Operators
- JavaScript Assignment
- JavaScript Data Types
- JavaScript Functions
- JavaScript Objects
- JavaScript Events
- JavaScript Strings
- JavaScript String Methods
- JavaScript Numbers
- JavaScript Number Methods
- JavaScript Arrays
- JavaScript Array Const
- JavaScript Array Methods
- JavaScript Sorting Arrays
- JavaScript Array Iteration
- JavaScript Date Objects
- JavaScript Date Formats
- JavaScript Get Date Methods
- JavaScript Set Date Methods
- JavaScript Math Object
- JavaScript Random
- JavaScript Booleans
- JavaScript Comparison And Logical Operators
- JavaScript If Else And Else If
- JavaScript Switch Statement
- JavaScript For Loop
- JavaScript Break And Continue
- JavaScript Type Conversion
- JavaScript Bitwise Operations
- JavaScript Regular Expressions
- JavaScript Errors
- JavaScript Scope
- JavaScript Hoisting
- JavaScript Use Strict
- The JavaScript This Keyword
- JavaScript Arrow Function
- JavaScript Classes
- JavaScript JSON
- JavaScript Debugging
- JavaScript Style Guide
- JavaScript Common Mistakes
- JavaScript Performance
- JavaScript Reserved Words
- JavaScript Versions
- JavaScript History
- JavaScript Forms
- JavaScript Validation API
- JavaScript Objects
- JavaScript Object Properties
- JavaScript Function Definitions
- JavaScript Function Parameters
- JavaScript Function Invocation
- JavaScript Closures
- JavaScript Classes
- Java Script Async
- JavaScript HTML DOM
- The Browser Object Model
- JS Ajax
- JavaScript JSON
- JavaScript Web APIs
- JS Vs JQuery
JavaScript Const
Block Scope
Block scope in JavaScript refers to the area within curly braces {} where variables are accessible. This concept became more prominent with the introduction of let and const in ES6 (ECMAScript 2015), as they both adhere to block scoping rules. Let's delve into block scope through examples and explanations.
Declaring Variables with let
The let keyword is used to declare variables with block scope. Consider this example:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Block Scope Example</title>
</head>
<body>
<script>
function blockScopeExample() {
let x = 10;
if (true) {
let y = 20;
console.log(x); // Output: 10
console.log(y); // Output: 20
}
console.log(x); // Output: 10
// console.log(y); // This line will throw a ReferenceError
}
blockScopeExample();
</script>
</body>
</html>
In this code, x is accessible both inside and outside the if block because it's declared using let with block scope. However, y is only accessible within the if block due to its block-level scope.
Constants and Block Scope with const
Similarly, the const keyword also adheres to block scoping rules. Constants declared with const cannot be re-assigned after declaration and maintain block-level scope.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Block Scope and Const Example</title>
</head>
<body>
<script>
function constBlockScopeExample() {
const PI = 3.14159;
if (true) {
const message = "Hello, world!";
console.log(PI); // Output: 3.14159
console.log(message); // Output: Hello, world!
}
console.log(PI); // Output: 3.14159
// console.log(message); // This line will throw a ReferenceError
}
constBlockScopeExample();
</script>
</body>
</html>
Here, PI and message are constants with block scope. They are accessible within the if block but not outside it due to block scoping rules.
Block Scope in Loops
Block scope is especially important in loop structures. Consider this example:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Block Scope in Loops Example</title>
</head>
<body>
<script>
function loopBlockScopeExample() {
for (let i = 0; i < 3; i++) {
console.log(i); // Outputs: 0, 1, 2
}
// console.log(i); // This line will throw a ReferenceError
}
loopBlockScopeExample();
</script>
</body>
</html>
In this loop, i is declared with let, creating a new variable i with each iteration. Due to block scope, each i exists only within its iteration, preventing conflicts or unintended side effects.
Hoisting and Block Scope
Variables declared with let or const are hoisted to the top of their block scope but remain uninitialized until their actual declaration. This phenomenon is known as the Temporal Dead Zone (TDZ).
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Temporal Dead Zone (TDZ) Example</title>
</head>
<body>
<script>
function temporalDeadZoneExample() {
console.log(myVariable); // This line will throw a ReferenceError
let myVariable = "Value";
}
temporalDeadZoneExample();
</script>
</body>
</html>
In this code, accessing myVariable before its declaration will result in a ReferenceError due to the TDZ. Variables in the TDZ exist but are not yet initialized.
Nested Block Scope
Block scopes can be nested within each other, with inner blocks having access to variables from outer blocks.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Nested Block Scope Example</title>
</head>
<body>
<script>
function nestedBlockScopeExample() {
let outerVar = 10;
{
let innerVar = 20;
console.log(outerVar); // Output: 10
console.log(innerVar); // Output: 20
}
console.log(outerVar); // Output: 10
// console.log(innerVar); // This line will throw a ReferenceError
}
nestedBlockScopeExample();
</script>
</body>
</html>
Practice Excercise Practice now
Not Real Constants
In JavaScript, the const keyword is often associated with the concept of constants, implying that variables declared with const cannot be changed after initialization. However, it's crucial to understand that JavaScript's const does not create true constants in the traditional sense. This distinction becomes particularly apparent when dealing with objects and arrays.
The Nature of const in JavaScript
When you declare a variable using const in JavaScript, you're telling the interpreter that the variable should not be reassigned. For primitive data types like numbers, strings, and booleans, this behavior is straightforward:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>JavaScript "Not Real" Constants</title>
</head>
<body>
<script>
const x = 10;
// x = 20; // This line will throw a TypeError
console.log(x); // Output: 10
</script>
</body>
</html>
In this example, attempting to reassign x to a new value like 20 will result in a TypeError because x is declared as a constant.
Objects and Arrays with const
However, the behavior of const becomes nuanced when dealing with objects and arrays. Consider this code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>JavaScript "Not Real" Constants</title>
</head>
<body>
<script>
const person = { name: "Alice", age: 30 };
person.age = 40; // This is allowed
console.log(person); // Output: { name: "Alice", age: 40 }
</script>
</body>
</html>
In this case, although person is declared using const, we can still modify the properties of the object. This behavior might seem contradictory to the idea of constants, but it's important to note that const in JavaScript only prevents the variable from being reassigned to a new value or reference. It does not make the variable or its properties immutable.
The same principle applies to arrays:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>JavaScript "Not Real" Constants</title>
</head>
<body>
<script>
const numbers = [1, 2, 3];
numbers.push(4); // This is allowed
console.log(numbers); // Output: [1, 2, 3, 4]
</script>
</body>
</html>
Here, the numbers array is declared as a constant, but we can still modify its contents using methods like push.
Immutability vs. Reassignment
To understand the distinction better, let's differentiate between immutability and reassignment:
- Immutability: Immutability refers to the inability to change the state of an object or variable after it's been initialized. True constants in programming languages are immutable.
- Reassignment: Reassignment involves giving a variable a new value or reference. Constants in JavaScript prevent reassignment but do not ensure immutability for complex data types like objects and arrays.
- When we say JavaScript's const is not real constants, we mean that it provides a level of protection against reassignment but does not guarantee immutability for objects and arrays.
Dealing with Immutability
To achieve immutability in JavaScript, especially for objects and arrays, you can follow certain practices. One common approach is to use techniques like object freezing (Object.freeze()) or object immutability libraries like Immutable.js. Here's an example using Object.freeze():
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>JavaScript "Not Real" Constants</title>
</head>
<body>
<script>
const person = Object.freeze({ name: "Alice", age: 30 });
// Attempting to modify properties will not work
person.age = 40;
console.log(person); // Output: { name: "Alice", age: 30 }
</script>
</body>
</html>
In this example, Object.freeze() makes the person object immutable, so any attempts to modify its properties will be ignored. This approach ensures that the object remains unchanged once created.
Benefits of "Not Real" Constants
While JavaScript's const may not enforce true immutability for complex data types, it still offers several benefits:
- Readability: Constants declared with const convey the intention that their values should not be re-assigned, enhancing code readability.
- Preventing Accidental Reassignments: const prevents accidental reassignments of variables, reducing the risk of unintentional bugs.
- Maintaining References: Even though the properties of objects and arrays can be modified, const ensures that the variable itself maintains its reference.
Practice Excercise Practice now
Primitive Values
In JavaScript, data types are broadly categorized into two categories: primitive and non-primitive (objects). Primitive values are basic data types that represent single values, and they are immutable, meaning they cannot be changed once created. These primitive types include numbers, strings, booleans, null, undefined, and symbols (added in ECMAScript 6). Let's delve into each of these primitive types with examples.
1. Numbers
Numbers in JavaScript are represented using the number primitive type. They can be integers, floating-point numbers, or even scientific notation numbers. Here's an example:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>JavaScript Primitive Values</title>
</head>
<body>
<script>
let num = 42; // Integer
let floatNum = 3.14; // Floating-point number
let scientificNum = 6.02e23; // Scientific notation
console.log(num); // Output: 42
console.log(floatNum); // Output: 3.14
console.log(scientificNum); // Output: 6.02e+23
</script>
</body>
</html>
2. Strings
Strings represent textual data and are enclosed in single (''), double ("") or backticks (``) quotes. They can contain letters, numbers, symbols, and spaces. Here's an example:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>JavaScript Primitive Values</title>
</head>
<body>
<script>
let firstName = 'John';
let lastName = "Doe";
let fullName = `John Doe`; // Using backticks for template literals
console.log(firstName); // Output: John
console.log(lastName); // Output: Doe
console.log(fullName); // Output: John Doe
</script>
</body>
</html>
3. Booleans
Booleans represent logical values, either true or false. They are often used in conditional statements and comparisons. Here's an example:
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>JavaScript Primitive Values</title>
</head>
<body>
<script>
let isLogged = true;
let hasPermission = false;
console.log(isLogged); // Output: true
console.log(hasPermission); // Output: false
</script>
</body>
</html>
4. Null and Undefined
Both null and undefined represent the absence of a value, but they are used in different contexts. null is explicitly assigned to indicate no value, while undefined is automatically assigned to variables that have not been initialized. Here's an example:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>JavaScript Primitive Values</title>
</head>
<body>
<script>
let nullValue = null;
let undefinedValue;
console.log(nullValue); // Output: null
console.log(undefinedValue); // Output: undefined
</script>
</body>
</html>
5. Symbols
Symbols are unique and immutable values introduced in ECMAScript 6. They are often used as property keys in objects to avoid naming collisions. Here's an example:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>JavaScript Primitive Values</title>
</head>
<body>
<script>
const symbol1 = Symbol('description');
const symbol2 = Symbol('description');
console.log(symbol1 === symbol2); // Output: false
</script>
</body>
</html>
Manipulating Primitive Values
Since primitive values are immutable, any operation that appears to modify a primitive value actually creates a new value. For example:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>JavaScript Primitive Values</title>
</head>
<body>
<script>
let num1 = 5;
let num2 = num1 + 3; // Creates a new value, num2 = 8
let str1 = 'Hello';
let str2 = str1 + ' World'; // Creates a new string, str2 = 'Hello World'
console.log(num2); // Output: 8
console.log(str2); // Output: Hello World
</script>
</body>
</html>
In the example above, num2 and str2 are new values created from operations on the original primitive values num1 and str1.
Passing Primitive Values to Functions
When passing primitive values to functions, the value is passed by copy, meaning changes within the function do not affect the original value. Here's an example:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>JavaScript Primitive Values</title>
</head>
<body>
<script>
function modifyValue(val) {
val += 10;
return val;
}
let originalValue = 5;
let modifiedValue = modifyValue(originalValue);
console.log(originalValue); // Output: 5
console.log(modifiedValue); // Output: 15
</script>
</body>
</html>
In the example above, originalValue remains unchanged after passing it to the modifyValue function because primitive values are passed by copy.
Practice Excercise Practice now
Constant Objects Can Change
The concept of constant objects in JavaScript can sometimes be confusing because while the object itself is constant (meaning the reference to it cannot be changed), the properties of the object can still be modified. This behavior is often misunderstood, so let's delve into the details of how constant objects work in JavaScript, with examples.
Understanding Constant Objects in JavaScript
In JavaScript, the const keyword is used to declare constants. When used with primitive values like numbers or strings, const ensures that the value remains constant and cannot be reassigned. However, when const is used with objects, the behavior is slightly different.
Constant Object Reference
When you use const to declare an object, what you are declaring as constant is the reference to that object, not the object itself. This means that you cannot reassign the variable to point to a different object, but you can still modify the properties of the object.
Let's see this in action with an example:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Constant Objects in JavaScript</title>
</head>
<body>
<script>
// Declare a constant object
const person = {
name: 'John',
age: 30
};
// Try to reassign the object reference
// This will throw an error: TypeError: Assignment to constant variable
// person = {};
// Modify the properties of the constant object
person.age = 35;
person.address = '123 Main St';
console.log(person); // Output: { name: 'John', age: 35, address: '123 Main St' }
</script>
</body>
</html>
In this example, we declared a constant object person with properties name and age. Trying to reassign person to a new object (commented line) would result in a TypeError since the reference is constant. However, we can still modify the properties of the person object without any errors.
Explanation
The reason for this behavior is that objects in JavaScript are stored as references in memory. When you use const with an object, the reference to the object cannot be changed. However, the properties of the object itself, such as its keys and values, can be modified.
Immutable Properties
If you want to ensure that the properties of an object cannot be modified, you can use techniques like Object.freeze() or libraries like Immutable.js. Let's see an example using Object.freeze():
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Immutable Properties in JavaScript</title>
</head>
<body>
<script>
const person = {
name: 'Alice',
age: 25
};
Object.freeze(person); // Make the object properties immutable
// Try to modify the properties (will not throw an error, but changes won't take effect)
person.age = 30;
person.address = '456 Elm St';
console.log(person); // Output: { name: 'Alice', age: 25 }
</script>
</body>
</html>
In this example, even though we try to modify the age and address properties of the person object after freezing it, these changes won't take effect. The object remains unchanged because its properties are now immutable.
Practice Excercise Practice now
Redeclaring
Redeclaring variables in JavaScript can lead to unexpected behavior and bugs in your code. This phenomenon occurs due to JavaScript's flexible variable declaration and hoisting behavior. Let's dive into what redeclaring means, its consequences, and how to avoid common pitfalls using examples.
Understanding Variable Redefinition in JavaScript
When you declare a variable in JavaScript using var, let, or const, you reserve a memory space for that variable to store values. Redeclaring refers to the act of declaring the same variable again within the same scope. JavaScript allows variable redeclaration with var, but not with let or const.
Redefining Variables with var
Let's start by looking at an example of redeclaring variables using var:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Variable Redefinition in JavaScript</title>
</head>
<body>
<script>
var name = 'Alice';
console.log(name); // Output: Alice
var name = 'Bob'; // Redeclaring 'name'
console.log(name); // Output: Bob
</script>
</body>
</html>
In this example, we first declare a variable name with the value 'Alice'. Later, we redeclare name with the value 'Bob'. This is allowed with var, but it can lead to confusion and unintended consequences in larger codebases.
Redefining Variables with let and const
Unlike var, variables declared with let and const cannot be redeclared within the same scope. Redeclaring a variable with let or const will result in a syntax error:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Variable Redefinition in JavaScript</title>
</head>
<body>
<script>
let name = 'Alice';
console.log(name); // Output: Alice
let name = 'Bob'; // SyntaxError: Identifier 'name' has already been declared
console.log(name);
</script>
</body>
</html>
Similarly, using const to declare a variable prevents redeclaration as well:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Variable Redefinition in JavaScript</title>
</head>
<body>
<script>
const name = 'Alice';
console.log(name); // Output: Alice
const name = 'Bob'; // SyntaxError: Identifier 'name' has already been declared
console.log(name);
</script>
</body>
</html>
Hoisting and Redeclaring
JavaScript also has a concept called hoisting, where variable declarations are moved to the top of their containing scope during the compilation phase. This can lead to unexpected behavior when combined with redeclaring variables:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Variable Redefinition and Hoisting in JavaScript</title>
</head>
<body>
<script>
console.log(name); // Output: undefined
var name = 'Alice';
console.log(name); // Output: Alice
</script>
</body>
</html>
In this example, the first console.log(name) statement outputs undefined because the variable name is hoisted to the top of the script, but its value is not assigned until later.
Avoiding Redeclaration Issues
- To avoid issues related to redeclaring variables, follow these best practices:
- Use let and const instead of var: Prefer let and const for variable declarations as they offer better scoping rules and prevent accidental redeclaration.
- Declare variables once: Avoid redeclaring variables within the same scope to maintain code clarity and reduce potential bugs.
- Use unique variable names: Choose descriptive and unique variable names to avoid conflicts and improve code readability.
- Be mindful of hoisting: Understand how hoisting works in JavaScript and write code with hoisting in mind to prevent unexpected behavior.
Practice Excercise Practice now
Const Hoisting
Hoisting in JavaScript is a behavior where variable and function declarations are moved to the top of their containing scope during the compile phase, while the actual assignments remain in place. This means that regardless of where variables and functions are declared in your code, they are effectively moved to the top of their scope.
Hoisting with var, let, and const
Before diving into const specifically, let's understand how hoisting works with var and let.
Hoisting with var:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hoisting with var</title>
</head>
<body>
<script>
console.log(age); // Output: undefined
var age = 30;
console.log(age); // Output: 30
</script>
</body>
</html>
In this example, the console.log(age) statement before the variable declaration doesn't throw an error but outputs undefined. This is because the declaration of var age = 30; is hoisted to the top, but the assignment (= 30) remains in place.
Hoisting with let:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hoisting with let</title>
</head>
<body>
<script>
console.log(age); // Error: Cannot access 'age' before initialization
let age = 30;
console.log(age); // Output: 30
</script>
</body>
</html>
With let, the behavior is different. Trying to access the variable before its declaration results in a ReferenceError. This is because let variables are hoisted to the top of their block scope, but they are not initialized until the actual declaration statement.
Hoisting with const
Now, let's delve into hoisting with const. The behavior of const is somewhat similar to let concerning hoisting.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hoisting with const</title>
</head>
<body>
<script>
console.log(age); // Error: Cannot access 'age' before initialization
const age = 30;
console.log(age); // Output: 30
</script>
</body>
</html>
As with let, trying to access a const variable before its declaration throws a ReferenceError. This is because, like let, const variables are hoisted to the top of their block scope but remain uninitialized until the actual declaration statement.
Hoisting and Temporal Dead Zone (TDZ)
One crucial aspect to understand with let and const is the Temporal Dead Zone (TDZ). The TDZ is the period between entering a scope and the actual initialization of a let or const variable.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Temporal Dead Zone (TDZ)</title>
</head>
<body>
<script>
console.log(age); // Error: Cannot access 'age' before initialization
let age = 30; // TDZ starts
console.log(age); // Output: 30
</script>
</body>
</html>
In this example, trying to access age before its declaration initializes the TDZ, leading to a ReferenceError. Once age is declared, it exits the TDZ, and accessing it works fine.
Hoisting in Functions
Hoisting also applies to function declarations:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hoisting with Functions</title>
</head>
<body>
<script>
sayHello(); // Output: Hello
function sayHello() {
console.log('Hello');
}
</script>
</body>
</html>
In this case, the sayHello function is hoisted to the top, so calling it before its actual declaration works without errors.
Practice Excercise Practice now
Products
Partner
Copyright © RVR Innovations LLP 2024 | All rights reserved - Mytat.co is the venture of RVR Innovations LLP