ES6 Introduction
ES6 Introduction
ES6 Introduction
10. Symbol Data Type: Symbols are a new primitive data type introduced
in ES6. They provide a way to create unique identifiers, which can be
used as property keys in objects.
11. Iterators and Iterables: ES6 introduced the concept of iterators and
iterables, which allow for custom iteration behavior over data structures
such as arrays, maps, and sets.
function example() {
if (true) {
var x = 10;
console.log(x); // Output: 10
}
console.log(x); // Output: 10
}
example();
//ex:2
function test(){
var a = 10;
console.log("Value of 'a' inside funuction", a);
}
test();
try{
console.log("Triyng to access 'a' defined in function ")
console.log(a);
}catch(e){
console.log(e.message);
}
Example:
const number = 42;
try {
number = 99;
} catch (err) {
console.log(err);
// Expected output: TypeError: invalid assignment to const 'number'
// (Note: the exact output may be browser-dependent)
}
console.log(number);
//ex:
function example() {
const z = 30;
console.log(z); // Output: 30
example();
// let example
function example() {
if (true) {
let y = 20;
console.log(y); // Output: 20
}
console.log(y); // ReferenceError: y is not defined
}
example();
function test() {
{
let a = 10;
const b = 5;
}
try{
console.log("We will get error when we try to access a b")
console.log(a, b);// error will be thrown here
} catch(e) {
console.log(e.message);
}
}
test();
Default parameters
function multiply(a, b = 1) {
return a * b;
}
console.log(multiply(5, 2));
console.log(multiply(5));
console.log(multiply());
In JavaScript, function parameters default to undefined.
function f(x = 1, y) {
return [x, y];
}
f(); //
f(2);
Note: The first default parameter and all parameters after it will not
contribute to the function's length.
//the default parameter value does not have access to the child scope of
the function body:
functions and variables declared in the function body cannot be referred
to from default value parameter initializers; attempting to do so throws a
run-time ReferenceError.
function go() {
return ":P";
}
// The default argument is evaluated at call time. Unlike with Python (for example), a
new object is created each time the function is called.
append(1);
append(2);
Rest parameters:
function sum(...theArgs) {
let total = 0;
for (const arg of theArgs) {
total += arg;
}
return total;
}
console.log(sum(1, 2, 3));
// Expected output: 6
console.log(sum(1, 2, 3, 4));
// Expected output: 10
Basic Syntax:
function f(a, b, ...theArgs) {
// …
}
Example 2:
function myFun(a, b, ...manyMoreArgs) {
console.log("a", a);
console.log("b", b);
console.log("manyMoreArgs", manyMoreArgs);
}
myFun(1);
// Console Output:
// a, one
// b, two
// manyMoreArgs, ["three", "four", "five", "six"]
# A function definition can only have one rest parameter, and the rest
parameter must be the last parameter in the function definition.
The rest parameter bundles all the extra parameters into a single
array, but does not contain any named argument
defined before the ...restParam.
The arguments object contains all of the parameters — including
the parameters in the ...restParam array — bundled into one array-
like object.
Example 3:
function multiply(multiplier, ...theArgs) {
return theArgs.map((element) => multiplier * element);
}
Array methods can be used on rest parameters, but not on the arguments object:
function sortRestArgs(...theArgs) {
const sortedArgs = theArgs.sort();
return sortedArgs;
}
console.log(sortRestArgs(5, 3, 7, 1)); // 1, 3, 5, 7
console.log(sortArguments(5, 3, 7, 1));
// throws a TypeError (arguments.sort is not a function)
function func1(a, b, c) {
console.log(arguments[0]);
// Expected output: 1
console.log(arguments[1]);
console.log(arguments[2]);
}
func1("Kumar","Karthik","ramesh");
The arguments object is useful for functions called with more arguments
than they are formally declared to accept, called variadic functions, such
as Math.min().
function longestString() {
let longest = "";
for (let i = 0; i < arguments.length; i++) {
if (arguments[i].length > longest.length) {
longest = arguments[i];
}
}
return longest;
}
Template Literals
- embeding variables and expressions within your strings.
- template strings/template literals are denoted using backticks ``
-the syntax ${} which is used to embed variables within the string.
Multiline strings, readability and maintainability
String interpolation:
const a = 5;
const b = 10;
//regular strings
console.log("Fifteen is " + (a + b) + " and\nnot " + (2 * a + b) + ".");
//template strings
console.log(`Fifteen is ${a + b} and
not ${2 * a + b}.`);
const user = {
name: "Marie",
age: 25,
};
const userProfile = `
<div>
<h2>Name: ${user.name}</h2>
<p>Age: ${user.age}</p>
</div>`
const sqlQuery =
`SELECT * FROM ${tableName} WHERE ${columnName} = '$
{searchValue}'
<script>
function TaggedLiteralEg(strings) {
document.write(strings);
}
TaggedLiteralEg `Hai CSE students`;
</script>
Arrow Functions:
Arrow function {()=>} is concise way of writing JavaScript functions
in shorter way.
Lamda functions
Anonymous functions
Arrow functions can be defined with zero or more parameters, on one or
more lines.
Ex1:
() => expr
() => {
statements
}
param => {
statements
}
Is shorter version of
console.log(arg1);
console.log(arg2);
};
logStuff('chicken', 'tuna', 'chips', 'cookie', 'soda', 'delicious');
// In this example...
// arg1 = 'chicken'
// arg2 = 'tuna'
// moreArgs = ['chips', 'cookie', 'soda', 'delicious']
Example2:
var add = (...args) => {
// Set a starting total
var total = 0;
// Add each number to the total
for (var i = 0; i < args.length; i++) {
total += args[i];
}
// Return to the total
return total;
};
add(2,3,4);
// 1. Remove the word "function" and place arrow between the argument
and opening body brace
(a) => {
return a + 100;
};
// 2. Remove the body braces and word "return" — the return is implied.
(a) => a + 100;
The parentheses can only be omitted if the function has a single simple
parameter. If it has multiple parameters, no parameters, or default,
destructured, or rest parameters, the parentheses around the parameter
list are required.
// Arrow function
(a, b) => a + b + 100;
const a = 4;
const b = 2;
// Traditional anonymous function (no parameters)
(function () {
return a + b + 100;
});
// Arrow function
(a, b) => {
const chuck = 42;
return a + b + chuck;
};
How to Use Array and object Destructuring in JavaScript
Arrow functions
let array = [10, 20, 30, 40, 50];
array.forEach(element => {
console.log(element);
});
console.log(squaredArray);
Limitations :
Arrow functions functions are limited and can’t be used in all situations:
They do not have their own bindings to this or super, and should not be
used as methods.
They cannot be used as constructors.
They cannot use the special arguments keyword.
Example:
// Data set of students
var Students = [
{ rollNo: 21, name: 'Alpha', prizesWon: 1 },
{ rollNo: 22, name: 'Beta', prizesWon: 3 },
{ rollNo: 23, name: 'Gamma', prizesWon: 0 },
{ rollNo: 24, name: 'Delta', prizesWon: 0 },
{ rollNo: 25, name: 'Omega', prizesWon: 1}
];
example 2:
// Using reduce() function with arrow functions
const totalPrizes = Students.reduce(
(accumulator, Student) => accumulator + Student.prizesWon, 0);
Destructuring:
Destructuring is a JavaScript expression that makes it possible to
unpack values from arrays, or properties from objects, into distinct
variables.
javaScript object destructing is about assigning properties to an object to
the individual variables.
It is about extracting data from arrays and objects and assign them to
variables.
Benefits while extracting the data from Arrays or object properties from
objects repeatedly.
let introduction = ["Hello", "I" , "am", "Sarah"];
let [greeting, pronoun] = introduction;
console.log(greeting);
console.log(pronoun);
or
let greeting, pronoun;
[greeting, pronoun] = ["Hello", "I" , "am", "Sarah"];
console.log(greeting);
console.log(pronoun);
let a, b, rest;
[a, b] = [10, 20];
console.log(a);
// Expected output: 10
console.log(b);
// Expected output: 20
[a, b, ...rest] = [10, 20, 30, 40, 50];
console.log(rest);
// Expected output: Array [30, 40, 50]
console.log(pronoun);
console.log(name);
console.log(greeting);
console.log(intro);
console.log(greeting);
console.log(pronoun);
console.log(name);//"Sarah"
console.log(country);//"Nigeria"
console.log(job);//Developer"
console.log(name);//"Sarah"
console.log(country);//"Nigeria"
console.log(job);//Developer"
console.log(name);//"Sarah"
console.log(job);//"Developer"
console.log(identity);//"Sarah"
console.log(res);//"Developer"
console.log(foo);//"Sarah"
Promises in Java Script
<!DOCTYPE html>
<html>
<body>
<script>
let success = true;
function getUsers() {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (success) {
resolve([
{ username: 'john', email: 'john@test.com' },
{ username: 'jane', email: 'jane@test.com' },
]);
} else {
reject('Failed to find the user list');
}
}, 1000);
});
}
Successful call completions are indicated by the resolve function call, and
errors are indicated by the reject function call.
promise constructor
function getUsers() {
return [
{ username: 'john', email: 'john@test.com' },
{ username: 'jane', email: 'jane@test.com' },
];
}
function findUser(username) {
const users = getUsers();
const user = users.find((user) => user.username === username);
return user;
}
console.log(findUser('john'));
function getUsers(callback) {
setTimeout(() => {
callback([
{ username: 'john', email: 'john@test.com' },
{ username: 'jane', email: 'jane@test.com' },
]);
}, 1000);
}
findUser('john', console.log);
Example
function getUsers() {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (success) {
resolve([
{ username: 'john', email: 'john@test.com' },
{ username: 'jane', email: 'jane@test.com' },
]);
} else {
reject('Failed to the user list');
}
}, 1000);
});
}
function onFulfilled(users) {
console.log(users);
}
function onRejected(error) {
console.log(error);
}
// getUsers() function
// ...
First, you see the asterisk (*) after the function keyword. The
asterisk denotes that the generate() is a generator, not a normal
function.
Second, the yield statement returns a value and pauses the
execution of the function.
let gen=generator();
console.log(gen);
Object [Generator] {}
the Generator object executes its body which outputs message 'invoked
1st time' at line 1 and returns the value 1 at line 2.
The yield statement returns 1 and pauses the generator at line 2.
Third time
result= gen.next();
console.log(result);
{ value: undefined, done: true }
General syntax:
function* name(param0) {
statements
}
function* name(param0, param1) {
statements
}
function* name(param0, param1, /* …, */ paramN) {
statements
}
Since a generator is iterable, you can use the for...of loop:
for (const g of gen) {
console.log(g);
}
function* forever() {
let index = 0;
while (true) {
yield index++;
}
}
let f = forever();
console.log(f.next());
console.log(f.next());
console.log(f.next());
A Bag is a data structure that has the ability to collect elements and
iterate through elements. It doesn’t support removing items.
class Bag {
constructor() {
this.elements = [];
}
isEmpty() {
return this.elements.length === 0;
}
add(element) {
this.elements.push(element);
}
* [Symbol.iterator]() {
for (let element of this.elements) {
yield element;
}
}
}
bag.add(1);
bag.add(2);
bag.add(3);
Summary
function* generator() {
['a', 'b', 'c'].forEach(value => yield value)
// This will give syntax error
}
Benefits of Generator Functions
if (!done) {
value.then((result) => {
//console.log("Initial fetch result=",result)
const nextStep = generator.next(result);
if (!nextStep.done) {
nextStep.value.then((finalResult) => {
console.log("Final result=",finalResult);
});
}
});
}
</script>
</body>
</html>
‘Async/ await’ in asynchronous programming
consuming/using promise
myFunction().then(
function(value) { /* code if successful */ },
function(error) { /* code if some error */ }
);
The await keyword can only be used inside an async function, we get
syntax error
The await keyword makes the function pause the execution and wait for
a resolved promise before it continues:
Syntax :
let value = await promise;
myDisplay();
</script>
</body>
</html>
Spread Operator
The spread operator (...) in JavaScript is used to expand elements of an
iterable (like an array or string) or object into places where multiple
elements/properties are expected.
//copying array
const array1 = [1, 2, 3];
const array2 = [...array1]; // Creates a copy of array1
console.log(array2); // Output: [1, 2, 3]
ex:2
const odd = [1,3,5];
const combined = [2,4,6, ...odd];
console.log(combined);
console.log(sum(...numbers)); // Output: 6
Concatenating Arrays:
const array1 = [1, 2, 3];
const array2 = [4, 5, 6];
const concatenatedArray = [...array1, ...array2]; // Combines both arrays
Merging Objects:
const obj1 = { a: 1, b: 2 };
const obj2 = { c: 3, d: 4 };
const mergedObject = { ...obj1, ...obj2 }; // Merges both objects
console.log(mergedObject); // Output: { a: 1, b: 2, c: 3, d: 4 }
example 2:
const obj1 = { a: { b: 1, c: 2 } };
const obj2 = { ...obj1 };
console.log(obj2); // Output: { a: { b: 1, c: 2 } }
[].push.apply(rivers, moreRivers);
console.log(rivers);
Modules in JavaScript
A Module is a chunk of code in an external file that performs a specific
task or function.
Modules allow you to split your code into smaller, self-contained units
that can be reused and maintained more easily.
Modules promote modularity , code readability and reduce the likelihood
of errors, enabling JavaScript developers to focus on specific
functionalities without getting overwhelmed by the entire program's
complexity.
If you want to import every public function from another module, use
the asterisk * keyword:
The value property represents the next value in the sequence, and
the done property indicates whether the iterator has reached the end
of the sequence.
function Iterator(array) {
let nextIndex = 0;
return {
next: function () {
if (nextIndex < array.length) {
return {
value: array[nextIndex++],
done: false,
};
} else {
return {
value: undefined,
done: true,
};
}
},
};
}
const array = [1, 2, 3, 4, 5];
const arrayValue = Iterator(array);
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
*/
Symbol
new type of primitive data type introduced in ES6
Symbol() - Symbols return unique identifiers
Used for representing unique values that can be used as identifiers or
keys of objects that won’t collide with keys of any other code that might
add to the object.
const sym1=Symbol();
console.log(sym1) ; // Symbol()
<!DOCTYPE html>
<script>
"use strict";
let id = Symbol("id");
alert(id); // TypeError: Cannot convert a Symbol value to a string
let id = Symbol("id");
alert(id.toString()); // Symbol(id), now it works
let id = Symbol("id");
alert(id.description); // id
Hidden” properties
Symbols allow us to create “hidden” properties of an object, that no other
part of code can accidentally access or overwrite.
For instance, if we’re working with user objects, that belong to a third-
party code.
<!DOCTYPE html>
<script>
"use strict";
let id = Symbol("id");
user[id] = 1;
alert( user[id] ); // we can access the data using the symbol as the key
</script>
Symbols can also be used to create constants, which are useful for
creating APIs. Constants are created by passing in an object with a
'constant' property set to true.
// Create a constant
const MY_CONSTANT = Symbol('MY_CONSTANT', { constant: true });
object keys:
const mySymbol = Symbol();
const myObject = {
[mySymbol]: 'Hello World'
};
console.log(myObject[mySymbol]);
// Create a constant
const MY_CONSTANT = Symbol('MY_CONSTANT', { constant: true });
Global symbols
If we want named symbols to have same entities. For instance, different
parts of our application want to access symbol "id" meaning exactly the
same property.
To achieve that, there exists a global symbol registry.
<!DOCTYPE html>
<script>
"use strict";
Static methods
Methods like Symbol.for() and Symbol.keyFor() are used for setting and
retrieve Symbols from the global Symbol registry.
Note that the "global Symbol registry" is only a fictitious concept and
may not correspond to any internal data structure in the JavaScript
engine.
The method Symbol.for(Stringkey) takes a string key and returns a
symbol value from the registry, Otherwise a new Symbol gets created in
the global Symbol registry with key.
while Symbol.keyFor(symbolValue) takes a symbol value and returns the
string key corresponding to it.
Well-known Symbols
Examples:
Symbol.iterator
Symbol.asyncIterator
Symbol.replace
Instance properties
Symbol.prototype.constructor
Symbol.prototype.description
let lib = {
name: "ABC",
};
lib["id"] = 5;
lib["id"] = 6; // The value is changed because it is String [KEY]!!
lib[Symbol("id")] = 123;
lib[Symbol("id")] = 124; //Not changed