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

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 type object.

Also new Boolean(false) will be created as true, this happens because of type coersion.

False values in Javascript

There are only 6 cases in javascript are 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 return 1

  • if true || 5 will return true

  • if false || 10 will return 10

  • if false && 5 will return false

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 like match, 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 considered immutable, because you cannot change its prototype.

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 in console.log or other functions.

Using for in will traverse not only the properties in the current object, but also in the __proto__.

in will check for property existance in the object AND __proto__.

__proto__: The key to access a reference to the object's prototype.

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__, the own-object property is returned and shadows the __proto__ one.

You can access the __proto__ one with own-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.

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 with delete]

  • 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]

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 Expression

You attribute it to a variable.

Returning Functions

Functions that are returned from other functions can be instantly called with:

Parameters (Arguments)

You can access the list of arguments by accessing the default variable arguments.

Rest Parameter

Using Spread Operator, but must always be the last parameter declared.

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 an object, if you call the function inside the object, this will reference the object, and if you call it in global scope it will reference the global scope.

IMPORTANT: this cannot be accessed by functions declared as arrow functions.

area: () => { return this.x * this.y };

const area = () => { return this.x * this.y };

getter and setter

It is also possible to defined the getters and setters using .defineProperty().

getter

setter

When working with setter always use the function name different from the property name.

It is common practice to just use _property.

call, apply, bind

Using .call() and .apply(), you can invoke a function passing this as parameter.

Using call

function.call(obj, ...args):

  • function: Is the function to be executed.

  • obj: Is the object to give the this context to the function.

  • args: Are additional parameters passed to the function.

Using apply

function.call(obj, [...args]):

  • function: Is the function to be executed.

  • obj: Is the object to give the this context to the function.

  • args: Are additional parameters passed to the function by Array.

Using bind

Allows encapsulating this inside the function, returning it.

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 declare Constructor Functions.

Public properties (the ones that will be returned) will be accessed with this.

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 by new and only the Constructor Functions use them.

    • [This __proto__ is NOT the same __proto__ from objects heritage]

Person.prototype.getAge = () => {} cannot access this.

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.

Arrow Function

More simple and direct approuch for declaring functions.

Downside is that they dont have their own this and arguments, 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 current Context it looks down in the stack.

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:

Closures

Is a function with static scope chain, that is defined the moment a function is created.

Thus, all functions in Javascript are closures.

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.

Exception Handling

Any data type can be thrown as an error. It doesnt have to be an Error object.

Destructuring

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 the Array.

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 only string | 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.

.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 the value.

  • Not Iterable.

They can be usefull for cache implementations.

.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.

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.

.has(el): Return true if element exists.

.add(el): Add objectelement.

.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

Creating an Iterator

To resolve this...

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.

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.

prototype methods

They depend on a created instance to be invoked.

static methods

Dont depend in created instances.

extends

Used to create a ``class` hierarchy.

When a class extends a another class, it must call super() before accessing this in the constructor.

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.

Let's suppose that we want to implement a way of having a length.

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.race()

Executes multiple promises at the same time, but returns only the first one that finishes.

Generators

They make possible to pause a function execution, allowing the use of loop event cooperatively.

Used in Iterators.

They use the next method to iterate over the available values during the function execution.

  • They return a { value: ..., done: ... }, following the Iterable protocol.

When a yield is found, the function execution is paused until the next is invoked again.

  • yield can accept a parameter that will be the value inside the next iterable return.

    • yield parameter.

  • yield also returns some value that can be passed from next(value).

return method closes this generator, and allows you to also return a specific value.

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 with next calls.

Creating an Iterator with Generator

Generator can also be used to syncronize async calls similar to async/await.

Async\Await

Facilitates iteration with asyncronous calls, waiting for the promise return.

Iterating over awaits

For iterating over array of promisses.

for async of

An easier way of iterating over arrays of promisses.

Garbage Collector

Registering Performance

Time

Last updated