Javascript
Data Types
The types are divided in primitives
and objects
.
Primitives
Primitive types are Immutable
number
string
boolean
symbol
object
undefined
Objects
Are values that represent a memory reference.
Anything that is not a primitive IS an object.
Wrapper
()
can change the type data.
Number
Is a primitive and immutable, internally represented by IEEE 754
and is 64 bits
.
Can handle values:
Decimal,
Octonal
0o | 0O
,Binary
0b | 0B
,Hexadecimal
0x | 0X
.
Binary Operators
When using binary representation.
|
Binary OR&
Binary AND^
Binary XOR~
Binary Negation<<
Binary Shift Left>>
Binary Shift Right>>>
Binary Shift Right with Sign
Convertion Number -> String
(Number).toString( (10 | 16 | 2 | 8) )
Convertion String -> Number
All of these will convert a number in string
to its value in number
.
~~string
: [This is the binary operator, and will double invert]+string
string - 0
string * 1
string / 1
With the exception of +
:
"10" + 0
will do the concatanation
Decimal Operation residue
Doing math operation in decimals may result in weird results, due to residues due to rouding.
This happens because of the IEEE 754 number representation.
You can then use
_lodash
libraries for calculations, if you need decimals precision with calculations.
String
Are primitive and immutable, internally represented by Unicode
UTF-16
.
String Literals
`
This is a literal created string
and they can support multiline
and also code injection with ${var_name}
`
Usefull string functions
.includes(substring)
: Checks for subtrings in the string.
.startsWith(substring)
: Checks for substring at the beginning of the string.
.endsWith(substring)
: Checks for substring at the end of the string.
.localeCompare(otherString)
: Do comparison of strings and returns -1, 0 or 1, ideal for sort
.
.match(RegExp)
: Return parts of the string based on the RegExp.
.search(RegExp)
: Return the firts position in the string found by the RegExp.
Similar to
.indexOf()
but with RegExp.
.replace((RegExp | string), string)
: Return a new string, with replaced data.
.slice(InitialIdx, FinalIdx)
: Return part of the string parameters are [InitialIdx, FinalIdx)
.
FinalIdx
could be negative, which will then count backwards.
.padStart(string) | .padEnd(string)
: Fill the string with char
at the beginning or end.
.trim() | .trimLeft() | .trimRight()
: Remove empty spaces.
Boolean
Are primitive and immutable, represented by true
and false
.
If created using the
new Boolean()
constructor they will be of typeobject
.Also
new Boolean(false)
will be created astrue
, this happens because of type coersion.
False values in Javascript
There are only 6 cases in javascript are evaluated to false
:
!!0 // [Only the Number 0 is evaluated to false]
!!NaN // [NaN also becomes false]
!!"" // [Only the empty string is evaluated to false]
!!false
!!undefined // [undefined is also evaluated to false]
!!null // [null object is evaluated to false]
Anything else will be evaluated to true
.
Using logical operators for value attribuition
The return in logical operators are the
own operands
if
1 || 2
will return1
if
true || 5
will returntrue
if
false || 10
will return10
if
false && 5
will returnfalse
let var = 0 || 2 // -> var = 2
let var = 1 || 2 // -> var = 1
let var = 1 && 2 // -> var = 2
let var = 0 && 2 // -> var = 0
Symbol
Are primitive, unique and immutable, and act as unique keys
in objects.
Being uniques, you can never compare them because they will always be different.
They are used internally in
for/of
, string functions likematch
,split
,replace
, and others.
Regular Expressions (RegExp)
Can be used for validating strings, or extracting data from strings.
Usefull RegExp functions
.test(string)
: Check if passed string has the RegExp pattern.
.exec(string)
: Return an array of usefull information, with for instance extracted
matched strings.
To be able to extract, inside the Pattern the section to be extracted must be envolved with
()
. Ex.:(\w+)@(\w+).com.br
Objects
Is a dynamic collection of properties defined by keys. These keys can ONLY be of type
string | Symbol
, other types will be converted.
The default primitive
Object
is consideredimmutable
, because you cannot change itsprototype
.
undefined and null
undefined
ideally means that whatever you are trying to access does not even exist.
null
ideally means that the value of something is not set.
Deleting keys
You can delete keys with delete obj.key
Comparing Objects
The comparison of objects is done by reference, thus, you will be comparing their memory reference, which will always be different.
Heritage with (Prototypes)
You can have heritage in objects, just like in classes, with prototypes
.
Although the
key: value
properties inherited by prototypes are NOT SHOWN inconsole.log
or other functions.
Using
for in
will traverse not only the properties in the currentobject
, but also in the__proto__
.
in
will check for property existance in theobject
AND__proto__
.
__proto__
: The key
to access a reference to the object's prototype.
const someAbstractObj = {
keyA: 'Some value'
}
const someObj = {
itsKey: 'Another Value',
__proto__: someAbstractObj
}
Every object created, has a default prototype
Object
.
This is why when you search for a unexistent key it returns undefined
. It will try to access in the current object, if not found, it will go to the object __proto__
and look there. If it doesnt find it again it will again look into __proto__
of that upper object and look there. It will do this until reaches the default prototype object
, and then return undefined
.
.hasOwnProperty(key)
: Check if a property key
exists in the CURRENT object, it will NOT look in __proto__
.
Duplicated properties in
own-object
and its__proto__
, theown-object
property is returned and shadows the__proto__
one.You can access the
__proto__
one withown-object.__proto__.property
.
Object API
Object.assign(targetObj, {}, {}, ...)
: To make a shallow copy multiple objects into one.
Similar to
Spread Operator
, thus, having nested objects will implicate in the copies of these properties being copies of its reference, and not hard copies of its data.
const new_obj;
Object.assign(new_obj, { key1: '', key2: '' }, { key3: '' }, ...);
Object.defineProperty(obj, key, { value, ...opts })
: Add a property with configuration options.
opts
:
configurable
: That a property be erased. [If a property can be deleted from the object withdelete
]enumerable
: That a property be enumered. [Will not show on console.log, and other funcs that show keys - It will be 'hidden']value
: Define the value for this property.writable
: That a property have its value altered. [Change values for this property]
let obj = {}
// If you pass only the `value`, the other options will be defaulted to false.
Object.defineProperty(obj, 'some_prop', {
'value': 'Some value'
});
Object.defineProperty(obj, 'some_prop', {
'enumerable': true,
'value': 'Some value',
'writable': true,
'configurable': true,
});
Object.preventExtensions(obj)
: Forbit that the object have new properties, but allow the edit
or remove
of existent ones.
Object.isExtensible(obj)
: Check if the preventExtensions
is enabled.
Object.seal(obj)
: Forbit that the object have new properties and remove
existent, but allow edit
of existent ones.
Object.freeze(obj)
: Forbit that the object have new properties, edit
and remove
of existent ones.
JSON
Data types that are accepted values in JSON.
number
string
boolean
object
array
null
Functions
A function is an object
that contains executable code.
In Javascript functions are first class, meaning that the can be:
Assigned to variables
Passed as parameters
Returned from other functions
Declaring
Function Declaration
Just like declaring vars with var
, the function is always declared in the beginning of the main scope.
This is called
hoisting
.
So you can 'call' this function before declaring it.
function a() {
...
}
Function Expression
You attribute it to a variable.
const a = function() {
}
Returning Functions
Functions that are returned from other functions can be instantly called with:
const a = () => {
return () => {
return 'Do something';
}
}
console.log( a()() );
const sum = (a, b) => a + b;
const sub = (a, b) => a - b;
const calculator = (fn) => {
return (a, b) => {
return fn(a, b);
}
}
console.log( calculator(sum)(2, 2) );
console.log( calculator(sub)(2, 2) );
Parameters (Arguments)
You can access the list of arguments by accessing the default variable arguments
.
const a = () => {
console.log(arguments); // -> { '0': 1, '1': 2, '2': 3 }
}
a(1, 2, 3, ...);
Rest Parameter
Using Spread Operator, but must always be the last parameter declared.
const a = (...args) => {
...
}
console.log( a(1, 2, 3, 4) );
this
An implicit variable that always references the object responsible for its invocation.
So, it does not matter if you declare a function in
global scope
or inside anobject
, if you call the function inside the object,this
will reference theobject
, and if you call it inglobal scope
it will reference theglobal scope
.
IMPORTANT:
this
cannot be accessed by functions declared asarrow functions
.
area: () => { return this.x * this.y };
const rec = {
x: 10,
y: 2,
area() {
return this.x * this.y;
}
}
const area = () => { return this.x * this.y };
const area = function() { return this.x * this.y };
const rec = { x: 10, y: 2, area };
console.log( area() ); // -> undefined
console.log( rec.area() ); // -> 20
getter and setter
It is also possible to defined the getters
and setters
using .defineProperty()
.
getter
const rec = {
x: 10,
y: 2,
get area() {
return this.x * this.y;
}
}
setter
When working with setter
always use the function
name different from the property
name.
It is common practice to just use
_property
.
const rec = {
set x(x) {
this._x = x;
}
set y(y) {
this._y = y;
}
get area() {
return this._x * this._y;
}
}
rec.x = 10;
rec.y = 2;
console.log( rec.area() ); // -> 20
call, apply, bind
Using .call()
and .apply()
, you can invoke a function passing this
as parameter.
const area = function() {
return Math.PI * Math.pow(this.radious, 2);
}
const area2 = function(fn, a, ...) {
return fn(Math.PI * Math.pow(this.radious, 2)) + a;
}
const circle = {
radious: 10,
area,
area2
}
// Traditional way invoking from the object
console.log( circle.area() ); // -> 314.12412
console.log( circle.area2(Math.round, 1) ); // -> 315
Using call
function.call(obj, ...args)
:
function
: Is the function to be executed.obj
: Is the object to give thethis
context to the function.args
: Are additional parameters passed to the function.
console.log( area.call(circle) ); // -> 314.12412
console.log( area2.call(circle, Math.round, 1) ); // -> 315
Using apply
function.call(obj, [...args])
:
function
: Is the function to be executed.obj
: Is the object to give thethis
context to the function.args
: Are additional parameters passed to the function byArray
.
console.log( area.apply(circle) ); // -> 314.12412
console.log( area2.apply(circle, [Math.round, 1]) ); // -> 315
Using bind
Allows encapsulating this
inside the function, returning it.
const calcArea = area2.bind(circle);
console.log( calcArea(Math.round, 1) ); // -> 315
new
You can create multiple objects
that share the same structure with Constructor Functions
.
So that you eliminate duplication and have more reusability.
By convention they are declared with Capital Letters.
IMPORTANT: Cannot use
arrow functions
to declareConstructor Functions
.
Public properties (the ones that will be returned) will be accessed with
this
.
const Person = function(name, city, year) {
this.name = name;
this.city = city;
this.year = year;
// This is private
let sex = 'whatever';
// Both of this works
this.getAge = () => {
return (new Date()).getFullYear() - this.year;
}
this.getAge = function() {
return (new Date()).getFullYear() - this.year;
}
}
const person1 = new Person(...);
const person2 = new Person(...);
By declaring the function inside, each person object will have a getAge()
of different instance
. Thus taking more memory.
To address this...
You declare the getAge()
inside the Constructor Funtion
prototype.
Every
function
has a property prototype__proto__
, linked to the object created bynew
and only theConstructor Functions
use them.[This
__proto__
is NOT the same__proto__
from objects heritage]
cannot access Person.prototype.getAge = () => {}this
.
const Person = function(name, city, year) {
this.name = name;
this.city = city;
this.year = year;
}
Person.prototype.getAge = function() {
return (new Date()).getFullYear() - this.year;
}
const person1 = new Person(...);
const person2 = new Person(...);
Now all the instances of Person
are inheriting the getAge
and sharing its code.
instanceof
With it, it is possible to check if a object
was created by a specific Constructor Function
, analysing all of its prototype chain.
const data = new Date();
console.log( date instanceof Date ) // -> True
Arrow Function
More simple and direct approuch for declaring functions.
Downside is that they dont have their own
this
andarguments
, so they end up inheriting from the upper closure.
Execution Context
Is the environment where our code is executed.
Composed by:
variable object
,scope chain
this
.
The execution context uses an ideia of Stack
.
Active Execution Context
...
Execution Context 2
Execution Context 1
Global Execution Context
Inside a function, it is possible to access variables outside, by using
scope chain
. So if the execution cant find a variable in currentContext
it looksdown
in thestack
.
Every function has a variable
this
that contains a reference to the object responsible its invocation.
There are examples that using arrow function
can help like:
const obj = {
p1: 10,
getP1() {
// In this case, if a normal function declaration was used, it would steel the 'this' reference
// So since arrow functions dont inject the 'this'....'this' keeps referencing 'obj'
const fn1 = () => {
return this.p1;
}
return fn1();
}
}
console.log(obj.getP1());
Closures
Is a function with static scope chain
, that is defined the moment a function
is created.
Thus, all functions in Javascript are closures
.
const v1 = 10;
function fn1() {
console.log(v1);
}
function fn2(fn1) {
const v1 = 100;
fn1();
}
fn2(fn1); // -> 10
Even though it seems logical that, if fn1
does not find the variable and looks at the upper scope, and then use the v1 = 100
, this is wrong.
When fn1
was declared, its closure was defined, so it's fixed that the v1
it will use is the v1 = 10
.
Despite static, the scope chain references objects in memory, and so, can be shared between more than one function.
function fn1() {
let v1 = 10;
// m1 and m2 share the same scope
return {
m1() {
console.log(++v1);
},
m2() {
console.log(--v1);
}
}
}
const obj = fn1();
obj.m1(); // -> 11
obj.m2(); // -> 10
Exception Handling
Any data type can be thrown
as an error. It doesnt have to be an Error
object.
try {
throw 'This is just a string';
} catch (e){
console.log(e); // -> 'This is just a string'
}
Destructuring
const [ var1 = '', var2 = '' ] = ['thing1', 'thing2'];
const { key1: var1 = '', key2: var2 = '' } = { key1: 'thing1', key2: 'thing2' };
Array
It is just an object
that offers operations to access and manipulate its properties.
arr.length
: Shows the number of elements inside the Array, but it also considers empty positions.
Then, it would show a wrong number of
used
positions.Thus, avoid using
delete
to remove elemnts from theArray
.
Mutator methods
They modify the Array
.
arr.push(el)
: Add element to the end.
arr.pop()
: Remove element from the end.
[Also returns the removed element]
arr.unshift(el)
: Add element at the beginning.
arr.shift()
: Remove element at the beginning.
[Also returns the removed element]
arr.splice()
: Removes, substitutes ou add, one or more elements in a specifig position.
[Also return the removed elements]
arr.sort(fn)
: Sorts the elements according to a function
.
[-1 and 0 the element stays where it is; 1 it inverts with the other one]
[It changes the
Array
in place, does not return a new one]
arr.reverse()
: Reverse the elements order.
arr.fill()
: Fills (all or specific interval) of the values with the specified value.
Array iteration
They iterate over Array
values.
arr.forEach(fn)
: Execute the given function
for each element.
arr.filter(fn)
: Returns a new
array with only the filtered elements.
arr.find(fn)
: Returns the first
element that returned true in the given function
.
arr.some(fn)
: Returns true if one or more elements returned true in the given function
.
arr.every(fn)
: Returns true if all the elements returned true in the given function
.
arr.map(fn)
: Returns a new
array based on the return of the given function.
arr.reduce(fn(result, current) => {})
: Return a value based on the return of the given function.
Accessor methods
They return specific information about the Array
.
arr.indexOf()
: Returns the position of the first found element.
arr.lastIndexOf()
: Returns the position of the last found element.
arr.includes()
: Return true if the given element exists.
arr.concat()
: Returns a new
array result of the concatenation.
arr.slice()
: Returns part of an array, given a [start, end) position.
arr.join()
: Converts the array to a string, joining the elements with a given separator.
Map
Is an object
that stores any set of key => value
of any kind of data type.
Different from a
object
that stores onlystring | Symbol
keys.
Atention: May result in memory leaks, if elements are not properly handled.
Since references to the keys might be lost, and the values inside the the Map will remain.
const timeUnits = new Map(
["second", 1],
["minute", 60],
["hour", 3600]
);
// Convert the Map back to array
Array.from(timeUnits);
.size
: Returns the amount of pairs.
.set(key, value)
: Add a key => value
pair.
.forEach(fn)
: Iterates over the Map fn(value, key) => {}
.
.has(key)
: Returns true | false
if a given key
exists.
.get(key)
: Returns the value | undefined
of a given key
.
.delete(key)
: Removes a pair key => value
of given key
, and returns true | false
.
.clear()
: Remove all the elements.
Weak Map
Similar to Map
, but allows only keys of type object
.
Maintain the references in a weak way.
This is because if the reference to the object, which is a
key
, is lost, it is not possible anymore to access thevalue
.
Not Iterable.
They can be usefull for cache
implementations.
const wm1 = new WeakMap();
.set(key, value)
: Add a key => value
pair.
.has(key)
: Return true
if key
exists.
.get(key)
: Return the value
of a given key
.
.delete(key)
: Removes a pair given a key
.
Set
Is an object
that stores unique elements of any kind of data type.
Kind of an
array
.
Does not allow duplicate elements.
Can be used to remove duplicates from
arrays
.
const charsets = new Set(['Some', 'Other', 'element']);
Array.from(Set)
: To show the set as array
.
.size
: Returns the amount of elements.
.add(el)
: Add an element.
If values already exists no error or warning is thrown.
.forEach(fn)
: Iterates over a Set given a function
.
.has(el)
: Returns true
if an element exists.
.delete(el)
: Removes a element and returns true | false
.
.clear()
: Removes all the elements.
Weak Set
Is a object
similar to Set
, but only allow values of type object
.
Like
Weak Map
, also maintain weak references.Also not Iterable.
const ws1 = new WeakSet();
.has(el)
: Return true
if element exists.
.add(el)
: Add object
element.
.delete(el)
: Delete element and return true | false
.
Iterables and Iterators
Are conventions
implemented by Arrays
, Maps
, Sets
and strings
, that make them iterable by a iteration protocol.
These Iterable objects are used by:
Used by
for _ of _
.Used by the
spread operator
.
How an iterator works
const langs = ['A', 'B', 'C'];
const iterator = langs[Symbol.iterator]();
// Will invoke the next element
iterator.next(); -> { value: 'A', done: false }
iterator.next(); -> { value: 'B', done: false }
iterator.next(); -> { value: 'C', done: false }
iterator.next(); -> { value: undefined, done: true }
Creating an Iterator
function createIterator(...args) {
let i = 0;
return {
next() {
if (i < args.length) {
return { value: args[i++], done: false }
}
else {
return { value: undefined, done: true }
}
}
}
}
const iterator = createIterator('A', 'B', 'C');
iterator.next();
iterator.next();
iterator.next();
iterator.next();
// This will not work because iterator is not ITERABLE
for (let val of iterator) {
...
}
To resolve this...
function createIterable() {
return {
[Symbol.iterator]() {
let i = 0;
return {
next() {
if (i < args.length) {
return { value: args[i++], done: false }
}
else {
return { value: undefined, done: true }
}
}
}
}
}
}
const iterable = createIterable('A', 'B', 'C');
// Now this works
for (let val of iterable){
...
}
Classes
Are a special type of function
that act as a template for object creation.
Classes dont suffer
hoisting
.They are similar to
Constructor Functions
.
// Class Declaration
class SomeClass {
}
// Class Expression
const SomeClass = class {
}
They have 3 different member types:
constructor
prototype methods
static methods
constructor
Is invoked at the moment of the class instanciation
, and serves to initialize a object.
class Square {
constructor (side){
this.side = side;
}
}
const obj = new Square(4);
prototype methods
They depend on a created instance
to be invoked.
class Square {
...
// Prototype method
toString() {
return `side: ${this.side}`;
}
}
const square = new Square(4);
square.toString();
static methods
Dont depend in created instances
.
class Square {
...
static fromArea(area) {
return new Square(Math.sqrt(area));
}
}
const square = Square.fromArea(16);
extends
Used to create a ``class` hierarchy.
When a class
extends
a another class, it must callsuper()
before accessingthis
in the constructor.
class Shape {
// Notice that the super class can call methods from sub-classes that extends him
toString() {
return this.calculateArea();
}
}
class Square extends Shape{
constructor (side) {
super();
this.side = side;
}
calculateArea () {
return Math.pow(this.side, 2);
}
toString() {
return `side: ${this.side} area: ${super.toString()}`;
}
}
class Circle extends Shape{
constructor (radius) {
super();
this.radius = radius;
}
calculateArea () {
return Math.PI * Math.pow(this.side, 2);
}
toString() {
return `radius: ${this.radius} area: ${super.toString()}`;
}
}
Proxy and Reflect
Proxy
Capable of intercepting diverse types of operations in a target object.
Trap methods for diverse events
related to objects.
apply()
construct()
defineProperty()
deleteProperty(target, key)
invoked when a property is deleted.
get(target, key)
invoked when a property is accessed.
getOwnPropertyDescriptor()
getPrototypeOf()
has()
isExtensible()
ownKeys()
preventExtensions()
set(target, key, value)
invoked when a property is defined in a object.
setPrototypeOf()
Ex.: Let's try to make a Factory of objects that will act as arrays.
const createArray = function () {
return {};
}
const arr = createArray();
arr[0] = 'A';
arr[1] = 'B';
arr[2] = 'C';
Let's suppose that we want to implement a way of having a length
.
const createArray = function () {
// First object is the object to be trapped.
// Second object is the Traps definitions.
return new Proxy({}, {
set(target, key, value) {
// This length is a created property to hold the length of elements
target.length = target.length || 0;
target.length++;
// We also have to implement this attribution otherwise the object will not save elements
target[key] = value;
},
get(target, key) {
// Accept only numbers as keys
if (typeof key === 'string' && key.match(/\d+/))
return target[key];
}
deleteProperty(target, key) {
if (key in target) {
target.length--;
delete target[key];
}
}
});
}
Modules
Imported modules are also hoisted
.
Promises
Are objects
responsible for modeling asyncronous behaviour, allowing its treatment in a more direct and easy way.
Promise.all()
Promise.all([
promise1,
promise2,
...
]).then((values) => {
const [p1Return, p2Return, ...] = values;
...
}).catch((e) => {
...
});
Promise.race()
Executes multiple promises at the same time, but returns only the first one that finishes.
Promise.race([
promise1,
promise2,
...
]).then((value) => {
...
}).catch((e) => {
...
});
Generators
They make possible to pause a function execution, allowing the use of loop
event cooperatively.
Used in Iterators.
function* forever() {
...
}
const foreverGenerator = forever();
They use the next
method to iterate over the available values during the function execution.
They return a
{ value: ..., done: ... }
, following theIterable
protocol.
// This executes the function
foreverGererator.next()
When a yield
is found, the function execution is paused until the next
is invoked again.
yield
can accept a parameter that will be thevalue
inside thenext
iterable return.yield parameter
.
function* forever() {
let i = 1;
while(true) {
...
yield i++;
}
}
const foreverGenerator = forever();
foreverGenerator.next(); // -> { value: 1, done: false }
foreverGenerator.next(); // -> { value: 2, done: false }
foreverGenerator.next(); // -> { value: 3, done: false }
foreverGenerator.next(); // -> { value: 4, done: false }
yield
also returns some value that can be passed fromnext(value)
.
function* forever() {
let i = 1;
while(true) {
...
let reset = yield i++;
if (reset === true) i = 1;
}
}
const foreverGenerator = forever();
foreverGenerator.next(); // -> { value: 1, done: false }
foreverGenerator.next(); // -> { value: 2, done: false }
foreverGenerator.next(); // -> { value: 3, done: false }
foreverGenerator.next(true); // -> { value: 1, done: false }
foreverGenerator.next(); // -> { value: 2, done: false }
foreverGenerator.next(); // -> { value: 3, done: false }
return
method closes this generator, and allows you to also return a specific value.
foreverGererator.return('end') // -> { value: 'end', done: true }
The throw
method throws an exception inside the generator, breaking the execution if the exception is not treated.
If error is handled with
try/catch
the execution may continue withnext
calls.
foreverGenerator.throw('error');
Creating an Iterator with Generator
function createIterable(...args) {
return {
*[Symbol.iterator]() {
let i = 0;
while (i < array.length) {
yield array[i++];
}
}
}
}
const langs = createIterable('A', 'B', 'C');
for (let lang of langs) {
console.log(lang);
}
Generator can also be used to syncronize
async calls similar to async/await
.
function sum(a, b) {
return new Promise((resolve) => {
setTimeout(() => {
resolve(a + b);
}, 1000);
});
}
function async(gen, result) {
const obj = gen.next(result);
if (obj.done) return;
obj.value.then((res) => {
async(gen, res);
});
}
async(function* (){
const a = yield sum(2, 2);
const b = yield sum(4, 4);
const c = yield sum(a, b);
console.log(c);
});
Async\Await
Facilitates iteration with asyncronous calls, waiting for the promise return.
Iterating over awaits
For iterating over array of promisses.
(async function() {
try {
const functions = [
sum(2, 2),
sum(4, 4),
];
const results = [];
for (let fn of functions) {
const result = await fn;
results.push(result);
}
const [a, b] = results;
const c = await sum(a, b);
} catch (e) {
...
}
});
for async of
An easier way of iterating over arrays of promisses.
(async function() {
try {
const functions = [
sum(2, 2),
sum(4, 4),
];
const results = [];
for await (let result of functions) {
results.push(result);
}
const [a, b] = results;
const c = await sum(a, b);
} catch (e) {
...
}
});
Garbage Collector
Registering Performance
Time
console.time("Label");
...
console.timeEnd("Label");
Last updated