Return values are just what they sound like — the values that a function returns when it completes.Some functions don't return a significant value, but others do.
In JavaScript, strings are a data type used to represent sequences of characters. JavaScript provides a wide range of methods and properties that you can use to work with strings. Here's an overview of some common string methods in JavaScript:
-
String Length:
length: Returns the number of characters in a string.
const str = "Hello, World!"; console.log(str.length); // Outputs: 13
if string has whitespace , the length property counts whitespaces as 1 character.
str = "Hello "; str.length -> 6 -
String Access:
- You can access individual characters in a string using bracket notation.
- strings are treated as sequences of characters, and they have a numeric index associated with each character
const str = "Hello"; console.log(str[1]); // Outputs: "e"
-
String Concatenation:
concat(): Combines two or more strings and returns a new string.
const str1 = "Hello"; const str2 = "World"; const combined = str1.concat(", ", str2); console.log(combined); // Outputs: "Hello, World"
-
Substring:
substring(): Returns a part of the string between two indices.
syntax:
text_string.substring(start,?end);
where end index is optional.
const str = "Hello, World!";
const substr = str.substring(0, 5);
console.log(substr); // Outputs: "Hello"-
String Search and Replace:
indexOf(): Returns the index of the first occurrence of a specified substring. it returns index as index-1.lastIndexOf(): Returns the index of the last occurrence of a specified substring.replace(): Replaces a specified substring with another string.
const str = "Hello, World!"; console.log(str.indexOf("World")); // Outputs: 7 console.log(str.replace("World", "Universe")); // Outputs: "Hello, Universe!"
-
String Case Modification:
toUpperCase(): Converts the string to uppercase.toLowerCase(): Converts the string to lowercase.
const str = "Hello, World!"; console.log(str.toUpperCase()); // Outputs: "HELLO, WORLD!"
-
Trimming Whitespace:
trim(): Removes leading and trailing whitespace from a string.
const str = " Hello, World! "; console.log(str.trim()); // Outputs: "Hello, World!"
-
String Splitting:
split(): Splits a string into an array of substrings based on a specified delimiter.
const str = "apple,banana,cherry"; const fruits = str.split(","); console.log(fruits); // Outputs: ["apple", "banana", "cherry"]
-
String Conversion:
toString(): Converts various data types to a string.
const num = 42; const str = num.toString(); console.log(str); // Outputs: "42"
These are just a few examples of the many methods available for working with strings in JavaScript. Strings are a fundamental part of JavaScript, and these methods can help you manipulate and manage text data effectively.
-
String replace We can replace the contents inside the string using .replace method.
let str = "Welcome to the js"; str.replace("js","javascript"); output => 'Welcome to the javascript'
-
ReplaceAll it is used to replace all characters in the string. let str = "Welcome to the js tutorial, js is dynamic language"; str.replace("js","javascript"); output => 'Welcome to the javascript,js is dynamic language';
Whereas ReplaceAll str.replaceAll("js","javascript"); output => Welcome to the javascript,javascript is dynamic language.
An object is a complex data type that represents a collection of key-value pairs, where keys are strings (or symbols in modern JavaScript) and values can be of any data type.
How Can we create objects in js
-
Object literal
The simplest way to create an object is using object literal notation. You define an object with curly braces and specify its properties and values. const person = { name: "John", age: 30, }; -
Contructor function
You can create objects using constructor functions. These functions act as blueprints for creating multiple instances of objects with the same properties and methods.- Using object literals is fine when you only need to create one object, but if you have to create more than one, as in the previous section, they're seriously inadequate.
a) first way of making it reusable is creating a function. inside function - create a obj and initialize prperties and methods.
function createPerson(name) {
const obj = {};
obj.name = name;
obj.introduceSelf = function () {
console.log(`Hi! I'm ${this.name}.`);
};
return obj;
}
b) this works fine but is a bit long-winded: we have to create an empty object, initialize it, and return it. A better way is to use a constructor. A constructor is just a function called using the new keyword. When you call a constructor, it will:
function Person(name) {
this.name = name;
this.introduceSelf = function () {
console.log(`Hi! I'm ${this.name}.`);
};
}
const salva = new Person("Salva");
salva.name;
-
Object.create()
The Object.create() static method creates a new object, using an existing object as the prototype of the newly created object. const person = { isHuman: false, printIntroduction: function () { console.log(`My name is ${this.name}. Am I human? ${this.isHuman}`); }, }; const me = Object.create(person); me.name = 'Matthew'; // "name" is a property set on "me", but not on "person" me.isHuman = true; // Inherited properties can be overwritten me.printIntroduction(); // Expected output: "My name is Matthew. Am I human? true"
-
let obj1 = {a:1,b:2}; let obj2 = {c:3,a:4}; syntax: Object.assign(target_object,source_object); // here we want to copy all the properties or say we want to merge the properties of obj2 in obj1. Object.assign(obj1,obj2) // target obj is obj1 and source obj2 is source object console.log(Object.assign(obj1,obj2)); // . output => {a: 4, b: 2, c: 3} here we can see on merging or copying the object a value is updated to 4 this is because object.assign behaves like below {a:1,b:2} <- {c:3,a:4} // the values flow from right to left so when merging or copying will start 1. first c value will be copied in object obj1 {a:1,b:2,c:3} 2. a will be copied , but obj1 still has the obj1 already so a will be replaced with the new value from the obj2.a {a:4,b:2,c:3}
Object.keys is a static method available on Object , which returns the collection or array of keys of an object.
const obj1= {
name:'john',
age:28,
height:162
}
to get the array of keys we can do :
Object.entries(obj1) -> ["name","age","height"]
-
The Object.values() static method returns an array of a given object's own enumerable string-keyed property values.
const object1 = { a: 'somestring', b: 42, c: false, }; console.log(Object.values(object1)); // Expected output: Array ["somestring", 42, false]
an object is a collection of key and value pairs, Object.entries convert each key value pair as an array object where first element is key and second is value.
const obj ={
name : 'john',
age:30
}
the first pair of key and value is
a) key : name
value : 'john'
b) key : age
value : 30
Object.entries will create a array of key and value pairs
like first pair will be
["name","john"]
["age",30]
and will return as [["name","john"],["age",30]]
Each key-value pair is an array with two elements: the first element is the property key (which is always a string), and the second element is the property value.
The hasOwnProperty() method of Object instances returns a boolean indicating whether this object has the specified property as its own property (as opposed to inheriting
const object1 = {};
object1.property1 = 42;
console.log(object1.hasOwnProperty('property1'));
// Expected output: true
console.log(object1.hasOwnProperty('toString'));
// Expected output: false
console.log(object1.hasOwnProperty('hasOwnProperty'));
// Expected output: false
The Object.groupBy() static method groups the elements of a given iterable according to the string values returned by a provided callback function. The returned object has separate properties for each group, containing arrays with the elements in the group.
syntax
Object.groupBy(items, callbackFn)
const inventory = [
{ name: "asparagus", type: "vegetables", quantity: 5 },
{ name: "bananas", type: "fruit", quantity: 0 },
{ name: "goat", type: "meat", quantity: 23 },
{ name: "cherries", type: "fruit", quantity: 5 },
{ name: "fish", type: "meat", quantity: 22 },
];
const result = Object.groupBy(inventory, ({ type }) => type);
/* Result is:
{
vegetables: [
{ name: 'asparagus', type: 'vegetables', quantity: 5 },
],
fruit: [
{ name: "bananas", type: "fruit", quantity: 0 },
{ name: "cherries", type: "fruit", quantity: 5 }
],
meat: [
{ name: "goat", type: "meat", quantity: 23 },
{ name: "fish", type: "meat", quantity: 22 }
]
}
*/
-
Object.defineProperty The Object.defineProperty() static method defines a new property directly on an object, or modifies an existing property on an object, and returns the object.
Object.defineProperty(obj, prop, descriptor)
descriptor tells whether the property can be writable, configurable, editable,value.
configurable : true/false - means object can be configured or deleted .
writable : true if the value associated with the property may be changed with an assignment operator. Defaults to false.
value
The value associated with the property. Can be any valid JavaScript value (number, object, function, etc.). Defaults to undefined.
const obj ={a:1};
obj.b = 2 -> it will add another property b to obj object.
so how does defineProperty makes a difference is that :
The Object.is() method is a built-in JavaScript method that compares two values for strict equality, similar to the === equality operator. However, there are some differences in how Object.is() behaves compared to ===.
Here's the key difference:
-
===(strict equality operator): Compares values to check if they are equal. It returnstrueif the values are strictly equal, meaning they have the same type and the same value. -
Object.is(): Compares values to check if they are the same. It returnstrueif the values are considered the same, according to the SameValueZero algorithm. This algorithm is almost the same as strict equality (===), with a few exceptions:NaNis considered equal toNaN(unlike===, whereNaNis not equal toNaN).-0(negative zero) is not considered equal to+0(positive zero).
Here's an example:
console.log(Object.is(5, 5)); // true (same as ===)
console.log(Object.is(0, -0)); // false (different from ===)
console.log(Object.is(NaN, NaN)); // true (different from ===)The primary use case for Object.is() is when you need to perform comparisons where the differences between NaN and -0 matter, or when you need to ensure the most accurate equality check possible. In most cases, === is sufficient for comparing values in JavaScript.
The Object.freeze() method in JavaScript is used to freeze an object, making it immutable. When an object is frozen, you cannot add, modify, or delete its properties or change its prototype. It essentially locks the object down, making it read-only and preventing any further changes to its structure.
Here's how to use Object.freeze():
const obj = {
prop1: 42,
prop2: "Hello",
};
Object.freeze(obj);
// Attempting to modify the object will have no effect and will not throw an error, but it will silently fail.
obj.prop1 = 100; // No effect
obj.prop3 = "New Property"; // No effect
// You can still access the object's properties.
console.log(obj.prop1); // Outputs: 42
// You can check if an object is frozen using Object.isFrozen()
console.log(Object.isFrozen(obj)); // trueKeep in mind that freezing an object is shallow, meaning that the properties of the object are frozen, but if the object's properties are themselves objects, those nested objects are not automatically frozen. If you want to deep freeze an object, you would need to recursively apply Object.freeze() to all nested objects and their properties.
Freezing an object is a way to ensure that its structure remains consistent and that it won't be accidentally modified in your code. It's useful for creating immutable data structures, but it should be used with caution, as it makes the object unchangeable.
The Object.seal() method in JavaScript is used to seal an object, making it non-extensible. When an object is sealed, you cannot add or delete properties from it, but you can still modify the values of its existing properties. It's a level of control between a completely open object and a frozen (immutable) object.
Here's how to use Object.seal():
const obj = {
prop1: 42,
prop2: "Hello",
};
Object.seal(obj);
// Attempting to add or delete properties will have no effect and will not throw an error.
obj.prop3 = "New Property"; // No effect
delete obj.prop1; // No effect
// You can still modify the values of existing properties.
obj.prop1 = 100; // Allowed
console.log(obj.prop1); // Outputs: 100
// You can check if an object is sealed using Object.isSealed()
console.log(Object.isSealed(obj)); // trueSealing an object is a way to prevent further expansion or contraction of its properties while still allowing you to change the values of existing properties. It's useful when you want to maintain the object's structure but don't need it to be fully immutable.
In JavaScript, descriptors are objects that define the properties of an object when using the Object.defineProperty(), Object.defineProperties(), or Object.create() methods. Descriptors specify how a property behaves in terms of its configurability, writability, enumerability, and value. There are typically three types of descriptors:
-
Data Descriptors:
- Data descriptors define properties with a value. They have the following attributes:
value: The value of the property.writable: A boolean indicating if the property's value can be changed.enumerable: A boolean indicating if the property appears infor...inloops andObject.keys().configurable: A boolean indicating if the property can be deleted or if its attributes can be changed.
- Data descriptors define properties with a value. They have the following attributes:
-
Accessor Descriptors:
- Accessor descriptors define properties that have getter and/or setter functions. They have the following attributes:
get: A function to retrieve the property's value.set: A function to set the property's value.enumerable: A boolean indicating if the property appears infor...inloops andObject.keys().configurable: A boolean indicating if the property can be deleted or if its attributes can be changed.
- Accessor descriptors define properties that have getter and/or setter functions. They have the following attributes:
-
Generic Descriptors:
- A generic descriptor can be used to define properties that have both value and getter/setter methods. You can include both
valueandget/setin a descriptor, but they cannot coexist.
- A generic descriptor can be used to define properties that have both value and getter/setter methods. You can include both
Here's an example of using Object.defineProperty() with descriptors:
const obj = {};
// Data descriptor
Object.defineProperty(obj, 'dataProperty', {
value: 42,
writable: true,
enumerable: true,
configurable: true,
});
// Accessor descriptor
Object.defineProperty(obj, 'accessorProperty', {
get: function() {
return 'Getter';
},
set: function(value) {
console.log('Setter:', value);
},
enumerable: true,
configurable: true,
});
console.log(obj.dataProperty); // Outputs: 42
obj.accessorProperty = 'New Value'; // Outputs: Setter: New Value
console.log(obj.accessorProperty); // Outputs: GetterThese descriptors are powerful tools for defining and controlling the behavior of object properties in JavaScript. They allow you to set fine-grained control over how properties can be accessed and modified.
Object.seal() and Object.freeze() are both methods in JavaScript that are used to make objects non-extensible and prevent changes to their properties, but they differ in the level of immutability they provide:
-
Object.seal():- Makes an object non-extensible, which means you cannot add or delete properties from the object.
- Allows you to modify the values of existing properties.
- The object's properties remain configurable, which means you can still change the attributes of the existing properties, such as their values or enumerability.
- The properties of nested objects within the sealed object are not automatically sealed. You need to seal them explicitly if needed.
-
Object.freeze():- Makes an object fully immutable, making it read-only and preventing any changes to its properties.
- You cannot add, delete, or modify the values of its properties.
- The properties of the frozen object become non-configurable and non-writable, which means they cannot be changed or deleted.
- The properties of nested objects within the frozen object are not automatically frozen. You need to freeze them explicitly if needed.
In summary, the key difference is that Object.seal() allows modifications to the values of existing properties and doesn't make the properties non-configurable, while Object.freeze() makes the object and its properties fully immutable, preventing any changes. The choice between them depends on the level of immutability you need for your specific use case.
Object destructuring is a feature in JavaScript that allows you to extract values from objects and bind them to variables in a more concise and convenient way. It provides an elegant method for extracting properties from objects and using them in your code. Object destructuring is commonly used in a variety of JavaScript scenarios, such as when working with function parameters or extracting data from complex objects.
Here's the basic syntax of object destructuring:
const { property1, property2, ... } = sourceObject;property1,property2, etc., are the names of the properties you want to extract fromsourceObject.sourceObjectis the object from which you are extracting the properties.
Here's an example:
const person = {
firstName: "John",
lastName: "Doe",
age: 30,
};
const { firstName, lastName } = person;
console.log(firstName); // "John"
console.log(lastName); // "Doe"In this example, object destructuring is used to extract the firstName and lastName properties from the person object and bind them to variables.
Object destructuring is not limited to extracting single properties; you can also destructure nested objects and provide default values for properties that may not exist. It makes your code more concise and easier to read, especially when working with complex data structures.
Here's an example of destructuring nested objects and providing default values:
const user = {
name: "Alice",
address: {
city: "New York",
zipCode: "10001",
},
};
const { name, address: { city, country = "USA" } } = user;
console.log(name); // "Alice"
console.log(city); // "New York"
console.log(country); // "USA"Object destructuring is a powerful and widely used feature in modern JavaScript, and it simplifies working with objects and their properties.
const [a, b] = array;
const [a, , b] = array;
const [a = aDefault, b] = array;
const [a, b, ...rest] = array;
const [a, , b, ...rest] = array;
const [a, b, ...{ pop, push }] = array;
const [a, b, ...[c, d]] = array;
const { a, b } = obj;
const { a: a1, b: b1 } = obj;
const { a: a1 = aDefault, b = bDefault } = obj;
const { a, b, ...rest } = obj;
const { a: a1, b: b1, ...rest } = obj;
const { [key]: a } = obj;
let a, b, a1, b1, c, d, rest, pop, push;
[a, b] = array;
[a, , b] = array;
[a = aDefault, b] = array;
[a, b, ...rest] = array;
[a, , b, ...rest] = array;
[a, b, ...{ pop, push }] = array;
[a, b, ...[c, d]] = array;
({ a, b } = obj); // parentheses are required
({ a: a1, b: b1 } = obj);
({ a: a1 = aDefault, b = bDefault } = obj);
({ a, b, ...rest } = obj);
({ a: a1, b: b1, ...rest } = obj);
You can iterate over the properties of an object in JavaScript using various methods. Here are some common ways to iterate through the properties of an object:
-
For...In Loop:
The
for...inloop allows you to iterate over the enumerable properties of an object. Here's an example:const person = { name: "John", age: 30, }; for (const key in person) { if (person.hasOwnProperty(key)) { console.log(key + ": " + person[key]); } }
Note the use of
hasOwnProperty()to ensure that you are only iterating over the object's own properties and not properties from the object's prototype chain. -
Object.keys(), Object.values(), Object.entries():
JavaScript provides several built-in methods to work with object properties:
Object.keys(object)returns an array of property names.Object.values(object)returns an array of property values.Object.entries(object)returns an array of key-value pairs.
Here's how you can use them:
const person = { name: "John", age: 30, }; const keys = Object.keys(person); const values = Object.values(person); const entries = Object.entries(person); console.log(keys); // Outputs: ["name", "age"] console.log(values); // Outputs: ["John", 30] console.log(entries); // Outputs: [["name", "John"], ["age", 30]]
-
Object.getOwnPropertyNames():
Object.getOwnPropertyNames(object)returns an array of all property names, including non-enumerable ones.const person = { name: "John", age: 30, }; const propertyNames = Object.getOwnPropertyNames(person); console.log(propertyNames); // Outputs: ["name", "age"]
Choose the method that best suits your needs based on whether you want to work with property names, values, or both, and whether you want to include non-enumerable properties or not.
Rest and spread are two features in JavaScript that are related to handling arrays and objects. They are denoted by the use of three dots (...). Let's discuss each of them:
Syntax:
const newArray = [...existingArray];
const newObj = {...existingObj};-
Arrays: The spread operator is used to make a shallow copy of an array. It allows you to expand an array or object into places where multiple elements or key-value pairs are expected.
const array1 = [1, 2, 3]; const array2 = [...array1, 4, 5]; console.log(array2); // Output: [1, 2, 3, 4, 5]
-
Objects: Similarly, for objects, the spread operator creates a shallow copy.
const obj1 = { a: 1, b: 2 }; const obj2 = { ...obj1, c: 3, d: 4 }; console.log(obj2); // Output: { a: 1, b: 2, c: 3, d: 4 }
Syntax:
function myFunction(...rest) {
// rest is an array containing all the arguments passed to the function
}-
The rest parameter allows you to represent an indefinite number of arguments as an array.
function sum(...numbers) { return numbers.reduce((acc, num) => acc + num, 0); } console.log(sum(1, 2, 3, 4)); // Output: 10
-
It is often used in function parameters to gather remaining arguments into an array.
function example(first, second, ...rest) { console.log(first); // Output: 1 console.log(second); // Output: 2 console.log(rest); // Output: [3, 4, 5] } example(1, 2, 3, 4, 5);
In summary, the spread operator is used to unpack elements from arrays or properties from objects, creating shallow copies. The rest parameter, on the other hand, is used in function parameters to gather up remaining arguments into an array.
Template literals, also known as template strings, are a way to work with strings in JavaScript that allows for embedding expressions within the string. They are denoted by backticks () and can contain placeholders ${expression}` that are replaced with the result of evaluating the expression.
Here's a simple example:
const name = "John";
const greeting = `Hello, ${name}!`;
console.log(greeting);
// Output: Hello, John!In this example, the template literal ${name} is a placeholder that gets replaced with the value of the name variable.
-
Multiline Strings: Template literals allow multiline strings without needing to concatenate or use escape characters:
const multiline = ` This is a multiline string using template literals. `;
-
Expression Interpolation: You can embed expressions directly within the string:
const a = 10; const b = 20; const result = `The sum of ${a} and ${b} is ${a + b}.`;
-
Tagged Templates: Advanced usage involves using a function (a tag function) to process the template literal. This is known as tagged templates.
function customTag(strings, ...values) { // Process strings and values here return "Processed result"; } const taggedResult = customTag`Value 1: ${x}, Value 2: ${y}`;
The
stringsarray contains the literal text parts, andvaluescontain the evaluated expressions.
Template literals provide a more concise and readable way to work with strings, especially when you need to include variables or expressions within the string. They are widely used in modern JavaScript for constructing strings in a more flexible and clean manner.
The nullish coalescing assignment (??=) operator, also known as the logical nullish assignment operator, only evaluates the right operand and assigns to the left if the left operand is nullish (null or undefined).
eg :
const a = { duration: 50 };
a.duration ??= 10;
console.log(a.duration);
// Expected output: 50
a.speed ??= 25;
console.log(a.speed);
// Expected output: 25
The DOM, or Document Object Model, is a programming interface and representation of the structure and content of a web document. It provides a way for programs (typically JavaScript) to interact with and manipulate the structure, style, and content of HTML and XML documents.
Key points about the DOM:
-
Document Structure:
- The DOM represents an HTML or XML document as a tree structure.
- Each element, attribute, and piece of text in the document is a node in this tree.
-
Programming Interface:
- The DOM provides a programming interface (API) for scripting languages like JavaScript to access and manipulate the content and structure of a document dynamically.
-
Dynamic Interaction:
- With the DOM, you can dynamically modify the content, structure, and style of a document based on user actions, events, or other conditions.
-
Platform and Language Agnostic:
- While JavaScript is the most commonly used language for DOM manipulation in web browsers, the DOM itself is language-agnostic. Other programming languages can also interact with the DOM using appropriate interfaces.
-
Tree Hierarchy:
- The DOM represents the document as a hierarchical tree, with the root being the
documentnode, followed by nodes representing HTML elements, attributes, and text.
<!-- Example HTML document structure --> <html> <head> <title>Document Title</title> </head> <body> <h1>Hello, World!</h1> <p>This is a paragraph.</p> </body> </html>
The corresponding DOM tree structure:
document ├── html │ ├── head │ │ └── title │ │ └── (text) │ └── body │ ├── h1 │ │ └── (text) │ └── p │ └── (text) └── (other nodes) - The DOM represents the document as a hierarchical tree, with the root being the
-
Manipulation and Events:
- You can use the DOM to create, modify, and delete elements, change their attributes, and respond to user events such as clicks and keyboard input.
The DOM is a crucial part of web development as it enables dynamic, interactive, and responsive web applications by allowing developers to manipulate the content and structure of web pages in real-time. It serves as a bridge between the static HTML content and the dynamic behavior controlled by scripts.
JS which is used for dynamically updating web pages or manipulating web pages uses this DOM.
The DOM (Document Object Model) is created by the browser when it parses an HTML or XML document. The process of creating the DOM is part of the initial rendering phase when a web page is loaded.
The DOM represents a document with a logical tree. Each branch of the tree ends in a node, and each node contains objects. DOM methods allow programmatic access to the tree. With them, you can change the document's structure, style, or content.
so objects of document and tree lioke structure of document object is DOM. The Document Object Model (DOM) is the data representation of the objects that comprise the structure and content of a document on the web.
note : A web page is a document that can be either displayed in the browser window or as the HTML source. In both cases, it is the same document but the Document Object Model (DOM) representation allows it to be manipulated. As an object-oriented representation of the web page, it can be modified with a scripting language such as JavaScript.
In the context of the DOM (Document Object Model), the term "document" refers to the top-level object that represents the entire HTML or XML document. The document object is a fundamental part of the DOM, and it provides an interface for interacting with the content and structure of the document.
Here are some key points about the document object:
-
Top-Level Object:
- The
documentobject is part of the DOM and is created automatically by the browser when it parses an HTML or XML document.
- The
-
Representation of the Document:
- The
documentobject represents the entire document as a hierarchical tree structure, where each node in the tree corresponds to an element, attribute, or piece of text in the document.
- The
-
Root of the DOM Tree:
- The
documentobject is the root of the DOM tree. All other elements and nodes are descendants of this root node.
- The
-
Access to Document Elements:
- Through the
documentobject, developers can access and manipulate elements in the document, change styles, modify content, add or remove elements, and handle events.
// Example: Accessing an element by its ID const myElement = document.getElementById('myElement');
- Through the
-
Document-Level Properties and Methods:
- The
documentobject provides various properties and methods that allow developers to interact with the document at a high level. For example,document.titleaccesses the title of the document, anddocument.createElement()creates a new HTML element.
// Example: Changing the title of the document document.title = 'New Document Title';
- The
-
Interface for Scripting Languages:
- The
documentobject serves as an interface for scripting languages like JavaScript to dynamically manipulate the document. It enables developers to create interactive and dynamic web pages.
- The
In summary, the document object is a central and crucial part of the DOM, providing a programming interface for interacting with the content and structure of a web document. While it's a key component of the DOM, it is distinct from the HTML document itself; it's a dynamic representation created by the browser for scripting languages to work with.
Using the Document Object Model The Document Object Model (DOM) is an API for manipulating DOM trees of HTML and XML documents (among other tree-like documents). This API is at the root of the description of a page and serves as a base for scripting on the web.
What is a DOM tree? A DOM tree is a tree structure whose nodes represent an HTML or XML document's contents. Each HTML or XML document has a DOM tree representation. For example, consider the following document:
HTML Copy to Clipboard
<html lang="en">
<head>
<title>My Document</title>
</head>
<body>
<h1>Header</h1>
<p>Paragraph</p>
</body>
</html>
The DOM as a tree-like representation of a document that has a root and node elements containing content Although the above tree is similar to the above document's DOM tree, it's not identical, as the actual DOM tree preserves whitespace.
When a web browser parses an HTML document, it builds a DOM tree and then uses it to display the document.
- The Document API, also sometimes called the DOM API, allows you to modify a DOM tree in any way you want. It enables you to create any HTML or XML document from scratch or to change any contents of a given HTML or XML document. Web page authors can edit the DOM of a document using JavaScript to access the document property of the global object. This document object implements the Document interface.
The Document interface in the DOM (Document Object Model) provides various methods for interacting with and manipulating the content, structure, and style of an HTML or XML document. Here are some of the commonly used methods:
-
getElementById(id: string): Element | null- Returns the element with the specified ID or
nullif not found.
- Returns the element with the specified ID or
-
getElementsByClassName(className: string): HTMLCollectionOf<Element>- Returns a live
HTMLCollectionof elements with the specified class name.
- Returns a live
-
getElementsByTagName(tagName: string): HTMLCollectionOf<Element>- Returns a live
HTMLCollectionof elements with the specified tag name.
- Returns a live
-
getElementsByName(name: string): NodeListOf<HTMLElement>- Returns a non-live
NodeListof elements with the specified name attribute.
- Returns a non-live
-
querySelector(selectors: string): Element | null- Returns the first element that matches the specified CSS selectors or
nullif not found. It is generally used for querying the elements directly using tag, class,id.
- Returns the first element that matches the specified CSS selectors or
-
querySelectorAll(selectors: string): NodeList- Returns a static
NodeListof all elements that match the specified CSS selectors.
- Returns a static
-
createElement(tagName: string): Element- Creates a new HTML element with the specified tag name.
-
createTextNode(data: string): Text- Creates a new text node with the specified content.
-
appendChild(newChild: Node): Node- Adds a new child node to the end of the list of children of a specified parent node.
-
removeChild(oldChild: Node): Node- Removes a child node from the DOM.
-
replaceChild(newChild: Node, oldChild: Node): Node- Replaces one child node with another.
-
getElementById(id: string): Element | null- Returns the element with the specified ID or
nullif not found.
- Returns the element with the specified ID or
-
getElementsByTagName(tagName: string): HTMLCollectionOf<Element>- Returns a live
HTMLCollectionof elements with the specified tag name.
- Returns a live
-
createElement(tagName: string): Element- Creates a new HTML element with the specified tag name.
-
createDocumentFragment(): DocumentFragment- Creates an empty
DocumentFragmentnode that can be used as a temporary container.
- Creates an empty
-
createEvent(eventInterface: string): Event- Creates a new event of the specified type.
-
open(): void- Opens a new document for writing.
-
close(): void- Closes the document for writing.
-
write(...text: string[]): void- Writes HTML expressions or JavaScript code to a document.
-
writeln(...text: string[]): void- Writes HTML expressions or JavaScript code to a document, followed by a newline character.
These are just a few examples of the methods provided by the Document interface. The actual set of methods can vary depending on the DOM specification and the version of the browser. It's recommended to refer to the official documentation or use browser developer tools for more comprehensive information and examples.
consider an element
<h1 id="heading" class="h1">Welcome to the Js </h1>
- we can change the textContent
-
to change the text content of the h1 element we need the element reference , which we can get using getElementById or querySelector or getElementsByClassName.
let element = document.getElementsByClassName("heading"); // to access or change the textcontent we have to get the textContent property of element element.textContent = "Text Changed";
- innerHTML Property
when we render content using textContent it is simple text format, but when we want the content to be changed and text contains html tags then we should use innerHTML.
element.innerHTML = "<i>Welcome</i>"
now content will be welcome in italic.
-
we can add or remove Styles
element.style.color = "red"; -
we can add classes
element.classList.add('heading1') -
remove classes
element.classList.remove('heading1') -
lets say we have a anchor tag and we want to dynamically update its href
-
<a href="" id="link">Click to Navigate</a> let anchortag = document.getElementById("link"); anchorTag.href="https.google.com";
Events are things that happen in the system you are programming — the system produces (or "fires") a signal of some kind when an event occurs, and provides a mechanism by which an action can be automatically taken (that is, some code running) when the event occurs.
For example:
- The user selects, clicks, or hovers the cursor over a certain element.
- The user chooses a key on the keyboard.
- The user resizes or closes the browser window.
- A web page finishes loading.
- A form is submitted.
- A video is played, paused, or ends.
- An error occurs.
In JavaScript, events represent occurrences or interactions that happen in the browser. Here are some of the commonly used events:
-
Mouse Events:
click: Occurs when the user clicks an element.dblclick: Occurs when the user double-clicks an element.mousedown: Occurs when the mouse button is pressed over an element.mouseup: Occurs when the mouse button is released over an element.mousemove: Occurs when the mouse pointer is moving while over an element.mouseover: Occurs when the mouse pointer enters an element.mouseout: Occurs when the mouse pointer leaves an element.
-
Keyboard Events:
keydown: Occurs when a key is pressed down.keyup: Occurs when a key is released.keypress: Occurs when a key is pressed and released.
-
Form Events:
submit: Occurs when a form is submitted.reset: Occurs when a form is reset.change: Occurs when the value of an input element changes.input: Similar tochange, occurs when the value of an input element changes.
-
Focus Events:
focus: Occurs when an element gets focus.blur: Occurs when an element loses focus.
-
Window Events:
load: Occurs when a page has finished loading.unload: Occurs when a page is being unloaded (closed or navigated away).resize: Occurs when the browser window is resized.scroll: Occurs when the user scrolls in an element.
-
Document Events:
DOMContentLoaded: Occurs when the HTML document has been completely loaded and parsed, without waiting for stylesheets, images, and subframes to finish loading.readystatechange: Occurs when the readyState property of the document changes (used in older versions of Internet Explorer).
-
Media Events:
play: Occurs when media playback begins.pause: Occurs when media playback is paused.ended: Occurs when media playback completes.
-
Drag and Drop Events:
dragstart: Occurs when the user starts dragging an element.dragend: Occurs when the user has finished dragging an element.dragover: Occurs when a dragged element is being dragged over a valid drop target.drop: Occurs when the dragged element is dropped on a valid drop target.
-
Animation Events:
animationstart: Occurs when a CSS animation starts.animationend: Occurs when a CSS animation completes.animationiteration: Occurs when a CSS animation completes one iteration.
These events are just a subset, and there are many more events available in the DOM. Additionally, custom events can be created using the CustomEvent constructor for more specialized use cases.
Event capturing and event bubbling are two phases of the event propagation process in the DOM (Document Object Model). These phases describe the order in which events are handled when they occur on a nested structure of HTML elements.
- Order: During the capturing phase, the event starts from the root of the DOM hierarchy and trickles down to the target element.
- Useful for: It can be useful for global operations or setups that need to be executed before the event reaches the target element.
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| root |
| | |
| | | |
| | | | |
| | | | | |
| | | | | | capturing phase |
| | | | | |-----------------------> target element |
| | | | | | |
| | | | | |
| | | | |
| | | |
| | |
| |
- Order: During the bubbling phase, the event starts from the target element and bubbles up to the root of the DOM hierarchy.
- Useful for: It is useful for handling events on specific elements and allows you to capture the event at various levels in the DOM hierarchy.
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| root |
| | |
| | | |
| | | | |
| | | | | |
| | | | | | bubbling phase |
| | | | | |<----------------------- target element |
| | | | | |
| | | | |
| | | |
| | |
| |
-
addEventListener:
- When you use
addEventListener, the third parameter is a boolean that specifies the event phase:truefor capturing andfalse(or omitted) for bubbling.
element.addEventListener('click', handler, true); // Capturing phase element.addEventListener('click', handler, false); // Bubbling phase (default)
- When you use
-
Legacy Methods:
- The older methods like
attachEvent(for Internet Explorer) do not support event capturing.
- The older methods like
-
To prevent an event from continuing through either the capturing or bubbling phase, you can use the
stopPropagationmethod.function handleClick(event) { // Handle the event event.stopPropagation(); // Stop the event from propagating further } element.addEventListener('click', handleClick, true); // Capturing phase
Understanding event capturing and bubbling is crucial for managing complex event handling scenarios, especially when dealing with nested HTML structures.
To stop the propagation of an event in JavaScript, you can use the stopPropagation() method. This method is available on the event object that is passed to your event handler function.
Here's an example:
<button id="parentButton">
Click me
<button id="childButton">Nested Button</button>
</button>
<script>
document.getElementById('parentButton').addEventListener('click', function (event) {
console.log('Parent button clicked');
// Stop the event from propagating further
event.stopPropagation();
});
document.getElementById('childButton').addEventListener('click', function (event) {
console.log('Child button clicked');
// The event will not reach the parent button due to stopPropagation
});
</script>In this example, when the nested button (childButton) is clicked, the event handler for the child button is triggered first. Inside that handler, event.stopPropagation() is called, preventing the event from reaching the parent button's event handler. As a result, the parent button's click event won't be triggered.
Here's a breakdown of the code:
- Clicking the child button triggers its event handler, logging "Child button clicked" to the console.
- The
event.stopPropagation()method is called in the child button's event handler, preventing the event from reaching the parent button. - As a result, the parent button's event handler is not executed.
Keep in mind that while stopPropagation() prevents the event from propagating to the parent and further up the DOM hierarchy, it doesn't prevent the default behavior associated with the event. If the event has a default action (e.g., following a link or submitting a form), you might also need to use event.preventDefault() to prevent that default action.
In the context of web development and JavaScript, the term "preventDefault" refers to a method that can be called on an event object to stop the default behavior associated with that event.
When an event occurs in a web page, such as a click on a link or a form submission, the browser performs a default action associated with that event. The preventDefault method allows you to stop this default behavior.
Here's an example using JavaScript and the DOM (Document Object Model):
document.getElementById('myLink').addEventListener('click', function(event) {
// Prevent the default behavior of the link click
event.preventDefault();
// Your custom code goes here
console.log('Link clicked, but default behavior prevented.');
});In this example, when a user clicks on the HTML element with the ID "myLink," the associated event listener is triggered. Inside the event listener, event.preventDefault() is called, preventing the default behavior of the link click, which would typically navigate to the URL specified in the href attribute.
This technique is often used in scenarios where you want to handle an event in a custom way without allowing the browser to perform its default action. It's commonly used with form submissions, link clicks, and other user interactions in web development.
-
Let's consider an example using an HTML form and JavaScript. Suppose you have a form with an input field and a submit button, and you want to prevent the form from being submitted when the user clicks the submit button. Instead, you want to perform some custom validation and handling. Here's how you can use preventDefault:
eg :
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Prevent Default Example</title>
</head>
<body>
<form id="myForm">
<label for="username">Username:</label>
<input type="text" id="username" name="username" required>
<button type="submit" id="submitButton">Submit</button>
</form>
<script>
document.getElementById('myForm').addEventListener('submit', function(event) {
// Prevent the default form submission behavior
event.preventDefault();
// Perform custom validation or handling
validateAndSubmit();
});
function validateAndSubmit() {
// Custom validation logic goes here
var usernameInput = document.getElementById('username');
var username = usernameInput.value;
if (username.length < 3) {
alert('Username must be at least 3 characters long.');
} else {
// If validation passes, you can perform the form submission or other actions
alert('Form submitted successfully!');
}
}
</script>
</body>
</html>
The read-only firstChild property of the Node interface returns the node's first child in the tree, or null if the node has no children.
eg :
<p id="para">
<span>hey</span>
</p>
Here first child is the text node.
- so if we do document.getElementById("para").firstChild it will return #text
In the above, the console will show '#text' because a text node is inserted to maintain the whitespace between the end of the opening
and tags. Any whitespace will create a #text node, from a single space to multiple spaces, returns, tabs, and so on.
The Element.firstElementChild read-only property returns an element's first child Element, or null if there are no child elements. Element.firstElementChild includes only element nodes. To get all child nodes, including non-element nodes like text and comment nodes, use Node.firstChild.
To specifically get the next and previous sibling elements (skipping text or comment nodes) in JavaScript, you can use the following methods:
-
nextElementSiblingProperty:- The
nextElementSiblingproperty returns the next sibling element of the specified element, excluding text nodes and comment nodes.
Example:
var currentElement = document.getElementById('exampleElement'); var nextElementSibling = currentElement.nextElementSibling;
- The
-
previousElementSiblingProperty:- The
previousElementSiblingproperty returns the previous sibling element of the specified element, excluding text nodes and comment nodes.
Example:
var currentElement = document.getElementById('exampleElement'); var previousElementSibling = currentElement.previousElementSibling;
- The
Here's a more complete example:
var currentElement = document.getElementById('exampleElement');
// Get the next sibling element
var nextElementSibling = currentElement.nextElementSibling;
if (nextElementSibling) {
console.log('Next Element Sibling:', nextElementSibling);
} else {
console.log('No next element sibling.');
}
// Get the previous sibling element
var previousElementSibling = currentElement.previousElementSibling;
if (previousElementSibling) {
console.log('Previous Element Sibling:', previousElementSibling);
} else {
console.log('No previous element sibling.');
}These properties directly provide the next and previous sibling elements of the specified element, making it convenient to work with element nodes specifically, excluding text nodes and comment nodes.
The appendChild() method of the Node interface adds a node to the end of the list of children of a specified parent node.
const p = document.createElement("p");
document.body.appendChild(p);
The contains method of a Node in JavaScript is used to check if a specific node is a descendant of the given node. It returns a boolean value: true if the node is a descendant, and false otherwise.
Here's an example to illustrate how the contains method works:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Node Contains Example</title>
</head>
<body>
<div id="parentDiv">
<p id="childParagraph">This is a paragraph inside a div.</p>
</div>
<script>
var parentDiv = document.getElementById('parentDiv');
var childParagraph = document.getElementById('childParagraph');
// Check if parentDiv contains childParagraph
var isChildInParent = parentDiv.contains(childParagraph);
if (isChildInParent) {
console.log('childParagraph is a descendant of parentDiv.');
} else {
console.log('childParagraph is not a descendant of parentDiv.');
}
</script>
</body>
</html>In this example:
- We have an HTML structure with a
<div>element (parentDiv) containing a<p>element (childParagraph). - In the script, we use
document.getElementByIdto get references to both the parent and child elements. - We then use the
containsmethod on theparentDivto check if it contains thechildParagraph. - The result is stored in the variable
isChildInParent, and we log a message based on the result.
When you run this script, it should log "childParagraph is a descendant of parentDiv" because the childParagraph is indeed contained within the parentDiv. If you were to change the parent-child relationship or check for containment in a different way, the result might be different. The contains method is useful for checking the hierarchy relationships between nodes in the DOM.
The insertBefore() method of the Node interface inserts a node before a reference node as a child of a specified parent node.
If the given node already exists in the document, insertBefore() moves it from its current position to the new position. (That is, it will automatically be removed from its existing parent before appending it to the specified new parent.)
Sets the value of an attribute on the specified element. If the attribute already exists, the value is updated; otherwise a new attribute is added with the specified name and value.
<button>Hello World</button>
const button = document.querySelector("button");
button.setAttribute("name", "helloButton");
- there are similar methods to setAttribute, like setAttribute sets or adds the new attribute same way,
removeAttributeremoves the attribute,getAttributereturns the value of attribute,if attribute not present it returns null.getAttributeNameswhich returns the array of attributes.
The Element.remove() method removes the element from the DOM
https://github.com/rohitsachdeva27/JS-Example-For-Drag-Drop
https://github.com/rohitsachdeva27/TicTacToeGame
API stands for Application programming interface. As we know js is client side programming language, it is used to render the data to be shown to the users, data which is dynamic.
When we say dynamic data, it means with each action of the user, data should be changed, or data should react to the user events. like :
- flipkart the site has the header which has options
MobilesMens, when user clicks on Mobiles , the user gets the data regarding onlu mobiles phones, is that data stored at client side ???
No - The data is stored at client side, the data is stored at server or we can say in layman language the central or distributed system.
Then how does js or our UI gets the data from that server.
The API stands for APPlication Programming Interface. API is an interface or communicating mechanism for 2 or more systems. when we say API is connecting or communicating mechanism it means that api lets 2 or more systems share data or communicate with each other.
So now we know API lets us commnunicate with the systems kept apart. key points how API let us communicate:
1. It defines the methods and data formats that applications can use to request and exchange information.
- means that API has some set of default conditions, which are methods, and it has also defined in which format data can be returned.
Here are some key points about APIs:
Communication Bridge
APIs serve as a bridge between different software systems, enabling them to interact and exchange data in a standardized way.
Abstraction:
APIs abstract the internal workings of a system, providing a clear and standardized interface for interacting with it. This allows developers to use the functionality of a system without needing to understand its internal implementation details.
Standardization:
APIs provide a standard way for developers to access the features or data of an application, service, or platform. This standardization facilitates interoperability and integration.
Data Format:
APIs often use standard data formats such as JSON (JavaScript Object Notation) or XML (eXtensible Markup Language) to structure the information being exchanged between systems.
HTTP and RESTful APIs:
Many modern APIs are built using the HTTP (Hypertext Transfer Protocol) and follow REST (Representational State Transfer) principles. These APIs are commonly referred to as RESTful APIs.
Endpoints:
APIs expose specific endpoints or URLs that developers can use to perform certain actions or retrieve specific information.
Now we understood that our js aplication can interact with the data over the other systems using API , which are bridge between them. but how actually does an API look like ????
API is basically an url or an endpoint.
lets consider API as messenger or a person who will pass the message to and fro.
There are 2 persons Person A and Person B, living far from each other. They want to communicate with each other, but they dont have any medium. so person B thought let me hire someone who will pass the data from here and there. IF person A needed to send some data, person A will call the messenger and give him the data, and messenger will pass the data to the person B, in return person B if needed to respond, will send the data through the messenger and messenger will deliver to the person A.
The messenger here for us in API, which carries the request and delivers the response. We just need to give the address and data to the messenger , it will deliver .
One more point, is it neccessary that only person A will request the data, it can also send the data or can request other actions.
- Those different actions are called methods, which are
GET,POST,DELETE,PATCH or PUT.
API endpoints are like channels through which different parts of a software application can communicate with each other. These endpoints are often associated with specific HTTP methods, such as GET, POST, PUT, or DELETE, which define the type of operation to be performed on the resource.
Consider a URL : https://api.example.com/users
In the URL "https://api.example.com/users," different parts can be identified based on the standard structure of a URL:
-
Scheme:
httpsis the scheme or protocol. It indicates how the resource is going to be accessed. In this case, it's using the Hypertext Transfer Protocol Secure (HTTPS). -
Domain:
api.example.comis the domain or hostname. It identifies the server where the resource is located. -
Path:
/usersis the path. It specifies the location or endpoint on the server where the desired resource can be found. In the context of an API, this often corresponds to a specific functionality or set of data, such as retrieving a list of users.
Collectively, the combination of the scheme, domain, and path forms the complete URL, specifying the address of the resource or service you want to access. In the example given, the URL is indicating that you are making a secure (HTTPS) request to the server at api.example.com and specifically targeting the "users" resource or functionality.
It's worth noting that URLs may also include additional components, such as:
-
Port: If a specific port is used, it would be included in the URL (e.g.,
https://api.example.com:8080). -
Query Parameters: These are additional parameters provided in the URL after a question mark (
?), typically used to pass information to the server. For example,https://api.example.com/users?limit=10might request only the first 10 users. -
Fragment: If the URL points to a specific section within a resource, a fragment identifier preceded by a hash (
#) can be included (e.g.,https://example.com/page#section1).
In the given example "https://api.example.com/users," the focus is on the scheme, domain, and path, indicating the secure access to the "users" resource on the server.
The Fetch API is a modern JavaScript API that provides an interface for making HTTP requests and handling responses. It is designed to be more flexible and powerful than the older XMLHttpRequest (XHR) object, offering a simpler and more consistent way to work with network requests in web applications.
Key features of the Fetch API include:
-
Promise-based: The Fetch API is promise-based, making it easier to work with asynchronous code. It uses the
Promiseobject to handle both successful responses and errors. -
Unified Request and Response: Unlike the XMLHttpRequest object, which separates the concepts of request and response, the Fetch API uses a unified
RequestandResponseobject model. This makes it easier to inspect and manipulate both request and response details. -
Stream Support: The Fetch API supports streaming of both request and response bodies, allowing for more efficient handling of large amounts of data.
-
Headers and CORS Support: It provides a
Headersobject for working with HTTP headers and supports Cross-Origin Resource Sharing (CORS) by default. -
JSON Handling: The Fetch API includes built-in methods for working with JSON data, making it convenient to send and receive JSON payloads.
Here's a basic example of using the Fetch API to make a simple GET request:
// Making a simple GET request
fetch('https://api.example.com/data')
.then(response => {
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.json(); // Parse the response as JSON
})
.then(data => {
console.log(data); // Handle the data
})
.catch(error => {
console.error('There was a problem with the fetch operation:', error);
});In this example, fetch returns a Promise that resolves to the Response object representing the response to the request. The code then checks if the response was successful (status code in the range 200-299), parses the JSON data if available, and handles any errors.
The Fetch API provides various options and configurations for different types of requests (GET, POST, etc.) and allows you to set headers, control caching behavior, and more. It has become the standard for making HTTP requests in modern web development.
We know that javascript is syncronous programming language, which means that it executes the code line by line.
refer to the blog for more desc. https://medium.com/@rohitsachdeva97/promises-and-asynchronous-programming-in-javascript-742de517762f
JavaScript Promises provide several methods to handle asynchronous operations in a more structured and readable way. Here are some of the commonly used Promise methods along with examples:
-
Promise.resolve(value):- Creates a Promise that is resolved with the given value.
const resolvedPromise = Promise.resolve("Resolved value"); resolvedPromise.then((result) => console.log(result)); // Output: "Resolved value"
-
Promise.reject(reason):- Creates a Promise that is rejected with the given reason.
const rejectedPromise = Promise.reject("Rejection reason"); rejectedPromise.catch((error) => console.error(error)); // Output: "Rejection reason"
-
Promise.all(iterable):- Returns a Promise that fulfills when all promises in the iterable are fulfilled or rejects when any of the promises is rejected.
const promise1 = Promise.resolve("One"); const promise2 = Promise.resolve("Two"); Promise.all([promise1, promise2]) .then((values) => console.log(values)); // Output: ["One", "Two"]
-
Promise.race(iterable):- Returns a Promise that fulfills or rejects as soon as one of the promises in the iterable fulfills or rejects.
const promise3 = new Promise((resolve) => setTimeout(resolve, 1000, "Three")); const promise4 = new Promise((reject) => setTimeout(reject, 500, "Four")); Promise.race([promise3, promise4]) .then((result) => console.log(result)) // Output: "Four" .catch((error) => console.error(error));
-
.then(onFulfilled, onRejected):- Attaches callbacks for the resolution and rejection of a Promise.
const fetchData = () => new Promise((resolve) => setTimeout(resolve, 1000, "Data")); fetchData() .then((data) => console.log(data)); // Output: "Data"
-
.catch(onRejected):- Attaches a callback for the rejection of a Promise.
const rejectedPromise = Promise.reject("Error"); rejectedPromise .catch((error) => console.error(error)); // Output: "Error"
-
.finally(onFinally):- Attaches a callback that is executed when the Promise is settled, regardless of whether it's fulfilled or rejected.
const fetchData = () => new Promise((resolve) => setTimeout(resolve, 1000, "Data")); fetchData() .then((data) => console.log(data)) .catch((error) => console.error(error)) .finally(() => console.log("Finally executed")); // Output: "Data" (after 1 second) and "Finally executed"
These are some of the main methods provided by the Promise object in JavaScript. They help in managing asynchronous code and handling the outcomes of asynchronous operations in a more organized manner.
async and await are features in JavaScript that simplify working with asynchronous code, making it look and behave more like synchronous code. They were introduced in ECMAScript 2017 (ES8) and provide a cleaner syntax for dealing with promises.
-
asyncFunction:- The
asynckeyword is used to define a function that returns a promise. - Inside an
asyncfunction, you can use theawaitkeyword to pause the execution of the function until the promise is resolved, and then the function resumes.
async function fetchData() { try { const response = await fetch('https://api.example.com/data'); const data = await response.json(); console.log(data); } catch (error) { console.error('Error fetching data:', error); } } fetchData();
- The
-
awaitExpression:- The
awaitkeyword is used to wait for a promise to resolve. It can only be used inside anasyncfunction. - When
awaitis used, it pauses the execution of theasyncfunction until the promise is settled (either fulfilled or rejected).
async function example() { const result = await somePromiseFunction(); console.log(result); }
Here,
somePromiseFunctionis assumed to return a promise. - The
The use of async and await makes asynchronous code more readable and maintainable compared to chaining .then() callbacks. It helps avoid the "callback hell" problem, making the code resemble synchronous code while still being asynchronous behind the scenes.
Remember that an async function always returns a promise. If the function explicitly returns a value, the promise will be resolved with that value. If the function throws an exception, the promise will be rejected with the thrown exception.
this represents an object that executes the current function. In short, this is defined by the function execution context. Such as how a function is called, it refers to a global object window. For example, when a function is being executed from a global object.
In JavaScript, call, apply, and bind are methods that allow you to control the value of this and pass arguments to functions in different ways.
-
call:- The
callmethod is used to invoke a function with a specifiedthisvalue and individual arguments passed as arguments (comma-separated).
function greet(name) { console.log(`Hello, ${name}!`); } greet.call(null, 'John');
In this example,
callis used to invoke thegreetfunction withthisset tonulland the argument'John'. - The
-
apply:- The
applymethod is similar tocall, but it takes an array or an array-like object as the second argument, which is unpacked as individual arguments for the function.
function introduce(firstName, lastName) { console.log(`My name is ${firstName} ${lastName}.`); } introduce.apply(null, ['John', 'Doe']);
Here,
applyis used to invoke theintroducefunction withthisset tonulland the arguments['John', 'Doe']. - The
-
bind:- The
bindmethod creates a new function that, when called, has itsthisvalue set to a specific value and prepends any provided arguments to the original function's arguments.
function saySomething(message) { console.log(`${this.name} says: ${message}`); } const person = { name: 'John' }; const sayHello = saySomething.bind(person, 'Hello'); sayHello(); // Output: John says: Hello
In this example,
bindis used to create a new functionsayHellowiththisset topersonand an additional argument'Hello'. - The
Key Differences:
callandapplyimmediately invoke the function, whilebindreturns a new function without immediately invoking it.callandapplyare similar; the primary difference is in how arguments are passed.bindis often used to create functions with a fixedthisvalue, which can be useful in scenarios like event handlers.
Common Use Cases:
- Changing the context of a function.
- Partial application of functions (pre-setting some arguments).
- Creating new functions with a fixed
thisvalue.
Remember that arrow functions in JavaScript do not have their own this and arguments. The behavior of call, apply, and bind is different when used with arrow functions compared to regular functions.
In JavaScript, classes are a way to define a blueprint for creating objects with shared properties and methods. The introduction of classes in ECMAScript 2015 (ES6) brought a more structured and familiar syntax for object-oriented programming in JavaScript.
Here's a basic example of a class definition:
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
greet() {
console.log(`Hello, my name is ${this.name} and I'm ${this.age} years old.`);
}
}
// Creating an instance of the class
const person1 = new Person('John', 30);
// Calling a method on the instance
person1.greet(); // Output: Hello, my name is John and I'm 30 years old.Let's break down the key concepts:
-
Class Declaration:
class Persondeclares a class namedPerson.
-
Constructor Method:
- The
constructormethod is a special method that is called when an object is instantiated from the class. It is used to initialize object properties.
- The
-
Instance Properties:
this.nameandthis.ageare instance properties, unique to each instance of the class.
-
Methods:
- The
greetmethod is a method of the class. Methods define behaviors associated with instances of the class.
- The
-
Instantiation:
const person1 = new Person('John', 30);creates an instance of thePersonclass with specific property values.
-
Instance Methods:
person1.greet();calls thegreetmethod on theperson1instance.
Classes provide a more organized and intuitive way to work with object-oriented programming concepts in JavaScript, but it's important to note that under the hood, JavaScript's prototype-based inheritance is still in play. Classes in ES6 are essentially syntactic sugar over the existing prototype-based model.
Javascript Version Features Added
Ecma script 2013 or es3 ECMAScript 3 laid the foundation for JavaScript development and was widely supported by browsers for many years.
Features:
- Primitive data types: Undefined, Null, Boolean,Number, and String.
- Conditional statements: if, else if, else.
- The Object constructor and prototype.
- Arrays and array manipulation methods
ECMAScript 4 (ES4) was a proposed version of the ECMAScript standard that underwent development but was eventually abandoned in favor of ECMAScript 5 (ES5). The development of ES4 faced challenges and disagreements within the ECMAScript community, and it was decided to abandon the ES4 effort in favor of a more incremental approach, leading to the eventual release of ES5.
Ecma Scrpipt 2015 or Es6 The 6th edition, ECMAScript 6 (ES6) and later renamed to ECMAScript 2015, was finalized in June 2015. • classes • Arrows • enhanced object literals • template strings • destructuring • default + rest + spread • let + const • iterators + for..of • modules • map + set + weakmap + weakset • symbols • subclassable built-ins • promises • math + number + string + array + object APIs • binary and octal literals • reflect api • tail calls
Es7 Features:
- Exponentiation Operator
- Array includes
Es8 (ecma 2017) Features :
-
Object.values();
-
Object.entires()
-
Object.getOwnPropertyDescriptors()
-
Async and await Es9 Features:
-
Rest /Spread
-
Promise.finally Es10 – Ecma-2019 Features:
-
String.matchAll()
-
Array.flat and flatMap()
-
Object.fromEntries()
-
Optional catch binding Es11 – Ecma script 2020 Features
-
Numeric Seprators
-
String.replaceAll()
-
??= and &&=
-
Promise.any
-
Private methods in class