Skip to content

Latest commit

 

History

History
309 lines (228 loc) · 13 KB

utils-javascript.md

File metadata and controls

309 lines (228 loc) · 13 KB

Javascript

SHORTHANDS

OPTIMIZATION

GARBAGE COLLECTOR

CONTEXT / HOISTING

Hoisting is JavaScript's default behavior of moving all declarations to the top of the current scope (to the top of the current script or the current function). Indeed all declarations, both functions and variables, are hoisted to the top of the containing scope, before any part of your code is executed.

  • Functions are hoisted first, and then variables.
  • Function declarations have priority over variable declarations, but not over variable assignments.

SCOPE

Scope determines the accessibility (visibility) of variables.

  • Local scope: Variables declared within a JavaScript function, become LOCAL to the function. They can only be accessed from within the function. They are deleted when the function is completed. Variables declared with var and let are quite similar when declared inside a function. They will both have Function Scope.
  • Global scope: A variable declared outside a function, becomes GLOBAL. A global variable has global scope: All scripts and functions on a web page can access it. Variables declared with var and let are quite similar when declared outside a block. They will both have Global Scope. In a web browser, global variables are deleted when you close the browser window (or tab).
  • Block scope: Variables declared with let inside a block {} cannot be accessed from outside the block.

With JavaScript, the global scope is the complete JavaScript environment. In HTML, the global scope is the window object. All global variables belong to the window object.

THIS / FUNCTIONS BORROWING METHODS

  • In other object-oriented programming languages, the this keyword always refers to the current instance of the class.

  • Whereas in JavaScript, the value of this depends on how a function is invoked (used or called). In JavaScript, the this keyword refers to different objects depending on how it is used... https://www.w3schools.com/js/js_this.asp

  • In JavaScript, you can use call(), apply(), and bind() methods to couple a function with an object. This way you can call the function on the object as if it belonged to it. In all 3 cases, the first argument is used as the value of this inside the function.

  • .call() - calls the same function with the specified arguments; in others words it allows for a function/method belonging to one object to be assigned and called for a different object.

  • .apply() - calls the same function with the arguments specified in an array; is very similar to call() but the only difference is that the apply method takes arguments as an array instead of separately.

  • .bind() - creates a new function with the same function body, with a preset value of this (the first argument) and returns that function. when the function is called, it has its 'this' keyword set to the provided value, with a given sequence of arguments preceding any provided when the new function is called. it is not necessary to pass the arguments at the time of bind. we can pass it later at the time of invocation.

  • https://blog.bitsrc.io/understanding-call-bind-and-apply-methods-in-javascript-33dbf3217be

  • https://stackoverflow.com/questions/15677738/whats-the-difference-between-call-apply-and-bind/15677775#15677775

FUNCTION

A function can be created in 4 ways:

  • function as a declaration
  • function as an expression
  • arrow function

PURE FUNCTIONS

IMMUTABILITY

DESTRUCTURING

ALGORITHM

EVENT LOOP

Being single-threaded, JS uses the concept of Event Loop to create the idea of running multiple tasks asynchronously. JS code only runs in one thread while JS uses Event Loop to run code asynchronously. The JS Engine is composed of a Call Stack, Heap and a Task Queue.

ARRAYS

IMPURE (avoid)

fill
pop
push
reverse
shift
sort
splice
unshift
reverse

OBJECTS

An object can be created in 4 ways

  • using object literals => let newObject = {};
  • using new or constructor => let newObject = new Object();
  • using Object.create() => let newObject = Object.create( Object.prototype );
  • using a class => let newObject = new User();

OBJECT LITERALS

In plain English, an object literal is a comma-separated list of name-value pairs inside of curly braces. Those values can be properties and functions. Here’s a snippet of an object literal with one property and one function.

let greeting = {
    fullname: "Michael Jackson",
    greet: (message, name) => {
        console.log(message + " " + name + "!!");
    }
};

MAPS

  • A Map is an unordered list of key-value pairs where the key and the value can be of any type like string, boolean, number, etc. For better understanding, we take an example of Map and its properties.
  • In a Weak Map, every key can only be an object and function or symbol in ES2023. It used to store weak object references. Since WeakMap does not create a strong reference to its keys, it will not prevent the object to be garbage collected.
var k1 = {a: 1};
var k2 = {b: 2};

var map = new Map();
var wm = new WeakMap();

map.set(k1, 'k1');
wm.set(k2, 'k2');

k1 = null;
map.forEach(function (val, key) {
    console.log(key, val); // k1 {a: 1}
});

k2 = null;
wm.get(k2); // undefined

ADVANCED

  • IIFE
  • Scope
  • Hoisting
  • Callstack
  • Currying
  • Callbacks
  • Promises
  • Closures
  • Iterators
  • Generators
  • Async await
  • Type coercion
  • DOM Manipulation
  • Prototype inheritance
  • Understanding "this" keyword
  • apply(), .call() and .bind()

PROMISE: CREATION

let promise = new Promise(function(resolve, reject) { 
    resolve(123); // immediately give the result: 123
});

PROMISE: ASYNC/AWAIT

const arr = [1, 2, 3];
// SYNC MAP
const syncRes = arr.map((i) => {
	return i + 1;
});
console.log(syncRes);
// 2,3,4

// VS ASYNC MAP
const asyncRes = await Promise.all(arr.map(async (i) => {
	await sleep(10);
	return i + 1;
}));
console.log(asyncRes);
// 2,3,4

// ERROR HANDLING
// return without await if you want to let the caller handle the error
// return with await if you want to handle the error locally
myLocalFunc() {
    try {
        return await fetch('http://myapi');
    } catch (error) {
        console.log('local error', error);
    }
}

OBSERVER API

PROXY

Proxies provide a unique way to modify or improve the behavior of existing objects at the lowest level. However, it is not perfect. There are limits. For example, it is not possible to do a comparison (===)with the original object. The proxy is a wrapper around an object, which forwards operations on it to the object, possibly trapping some of them. It can wrap any type of object, including classes and functions. Proxies can catch many operators, such as new (with construct), in (with has), delete (with deleteProperty), etc. One of the most obvious use case is when you can't modify the existing object because it's an external library or a generated code then you can use the proxy to modify or extend this part of the code.

EXAMPLES

OBJECTS

Useful object methods: keys, values, and entries.

const data = {
    name: 'Pierre',
    age: 32
}

// Give me the keys in an array
Object.keys(data);
// ['name', 'age']

// Give me the values in an array
Object.values(data);
// ['Pierre', 32]

// Give me the keys and the values in an array (converts an object → array)
const a = Object.entries(data)
// [['name', 'Pierre'], ['age', 32]]

// Give me the key-value pairs in an object. (converts an array → object)
const b = Object.fromEntries(a);
// { name: 'Pierre', age: 32 }

// Filter object properties by key in ES6 (solution 1)
const allowed = ['name'];
const filtered = Object.fromEntries(
   Object.entries(data).filter(([key, val])=> allowed.includes(key))
);
// { name: 'Pierre' }
// Filter object properties by key in ES6  (solution 1)
const filtered = allowed
  .reduce((obj, key) => ({ ...obj, [key]: data[key] }), {});
// { name: 'Pierre' }

MERGE

You can create a new object with condition based on others objects

const data = {
    ...(myVar1 && { myProperty1: myVar1}),
    ...(myVar2 && { myProperty1: myVar2}),
}

DEFINITION

  • nullish coalescing operator (??) is a logical operator that returns its right-hand side operand when its left-hand side operand is null or undefined, and otherwise returns its left-hand side operand. Best practices to use it instead of (||) to provide default value because of the fasly potential issue (eg. '' or 0).
  • logical nullish assignment (x ??= y) operator only assigns if x is nullish (null or undefined).
  • logical OR assignment (x ||= y) operator only assigns if x is falsy.
  • optional chaining operator (?.) permits reading the value of a property located deep within a chain of connected objects without having to expressly validate that each reference in the chain. Instead of causing an error if a reference is nullish (null or undefined), the expression short-circuits with a return value of undefined.
  • typeof operator returns a string indicating the type of the unevaluated operand; there is only 3 combination possible: "number", "string", "boolean", "object", "function" and "undefined".
  • non-null assertion operator (myExpr!;) tell the Typescript compiler explicitly that an expression has value other than null or undefined

MEASURE

console.time('test1'); console.timeEnd('test2);

EVOLUTION

2023