Modern Js Flashcards

1
Q

Clone an object

A

Use Object.assign() for shallow clone

const car = {
  color:'red'
}

const secondCar = Object.assign({}, car)

structuredClone(obj)

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

this keyword

A

this refers to the object that is currently executing the code.

The value of this depends on how a function is called:
When a function is called as a method of an object, this refers to the object itself.

When a function is called as a standalone function, this refers to the global object (in non-strict mode) or undefined (in strict mode).

When a function is called using the new keyword to create an instance of an object (constructor invocation), this refers to the newly created instance.

When a function is called using the call, apply, or bind methods, this is explicitly set to a specified value.

Arrow functions do not have their own this context; they inherit this from the enclosing lexical context.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

call, apply, bind

A
  1. call method is used to invoke a function with specified this
const obj = { name: 'John' };
function greet(message) {
    console.log(`${message}, ${this.name}`);
}
greet.call(obj, 'Hello'); // Output: Hello, John
  1. apply method is similar to call but takes arguments as array
const obj = { name: 'John' };
function greet(message) {
    console.log(`${message}, ${this.name}`);
}
greet.apply(obj, ['Hello']); // Output: Hello, John
  1. bind method creates a new function with this set
const obj1 = { name: 'John' };
const obj2 = { name: 'Alice' };
function greet(message) {
    console.log(`${message}, ${this.name}`);
}
const greetJohn = greet.bind(obj1);
const greetAlice = greet.bind(obj2);
greetJohn('Hello'); // Output: Hello, John
greetAlice('Hi');   // Output: Hi, Alice
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

Object.entries

A

Object.entries returns an iterator with array of key value pairs

for(const [key, val] of Object.entries(car)){
  console.log(key, val);
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

Spread and rest

A
  • spread operator expands array, object
let person = {
  name : "Alberto",
  surname: "Montalesi",
  age: 25,
}

let clone = {...person};
const name = ["Jon", "Paul", "Jones"];

function greet(first, last) {
  console.log(`Hello ${first} ${last}`);
}
greet(...name);
  • rest operator condenses multiple elements into single
const runners = ["Tom", "Paul", "Mark", "Luke"];
const [,,...losers] = runners;

console.log(...losers);
// Mark Luke
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

Promise

A

A Promise is an object representing the eventual completion or failure of an asynchronous operation.

const myPromise = new Promise((resolve, reject) => {
  // your code goes here
});

Promise.all
.race
.any

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

Hoisting

A

variables declared with var and functions are hoisted on the top of the scope. Only declarations are hoisted not values assigned. let and const are hoisted but are not accessible as they are in dead temporal zone

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q

Closures

A

all functions are closures in JavaScript.

a closure is a function that can access the variables from another function’s scope. This is possible by creating nested functions. The enclosing/outer function will, however, not have access to the inner scope.

Each function stores it’s inner lexical environment and outer lexical environment as well.

Closure happens when a function is declared not when called

for(let i=0; i<3;i++){
setTimeout(()=>{
console.log(i)
}, 500)
}

this will print 0 1 2, with var it will print 3 3 3

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q

Can we use multiple awaits in same line

A

Yes

num * await x * await y;
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q

Output of the code

const array = [5, 11, 18, 25];
for (var i = 0; i < array.length; i++) {
  setTimeout(function() {
    console.log('Element: ' + array[i] + ', at index: ' + i);
  }, 3000);
}
A

Element: undefined, at index: 4
Element: undefined, at index: 4
Element: undefined, at index: 4
Element: undefined, at index: 4

as array[4] is undefined and i is 4 outside the loop

Correct way

const array = [5, 11, 18, 25];
for (var i = 0; i < array.length; i++) {
  setTimeout(function (j) {
    console.log('Element: ' + array[j] + ', at index: ' + j);
  }, 3000, i);
}

or

use let to declare i instead of var

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q

Return nth cat
~~~
function returnNthCat(n){
const state = {
cats : [
{catId : 1 , name : “tom”},
{catId : 2 , name : “tiggy”},
{catId : 3 , name : “leo”},
{catId : 4 , name : “nixie”}
],
curpage : 3
}

}
~~~

A
function returnNthCat(n){
const state = {
   cats : [
      {catId : 1 , name : "tom"},
      {catId : 2 , name : "tiggy"},
      {catId : 3 , name : "leo"},
      {catId : 4 , name : "nixie"}
   ],
   curpage : 3
}

const {cats: {[n]: {name:cat}}} = state;

return cat;
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q

What is the use of callstack, event queue and event loop

A
  • call stack is used to keep track of all the function calls
  • event queue is keep track of any async api calls or async activity. When callstack encounters any async activity it pops that and moves that to event queue.
  • microtask queue
  • dom manipulations
  • The event loop has the task of checking both the call stack and the task queue continuously. When it sees that the call stack is done executing all the commands and is empty, it pops the commands from the task queue and pushes them into the call stack for execution. Then it runs microtask queue and dom manipulations
  • promise callbacks get higher priority that event callbacks and timers

use chunking to split long tasks to smaller ones

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
13
Q

What is event bubbling, capturing and target

A
  • event bubbling - the event bubbles from the button/tab click to the parent till the document. All the handlers from button to the document are called.
  • event capturing phase calls the event handlers from document till the element/button
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
14
Q

Event delegation

A

instead of adding a event listener on all child elements we can attach event to a parent element and in the listener find which child element was clicked. With this we dont need to add listener on each child element

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
15
Q

Object.freeze(), Object.seal()

A

Object.freeze() - prevents modification to existing properties
Object.seal() - prevents addition and deletion of properties

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
16
Q

Prototypal inheritance

A

Object.create
prototype.constructor
call(this)

function Human(name, age) {
    this.name = name;
    this.age = age;
};

function Man(name,age) {
    Human.call(this, name, age);
};

Man.prototype = Object.create(Human.prototype);
Man.prototype.constructor = Man;

function check(){
    var obj = new Man("Tommy Tan",20);
    console.log(obj.name) 
    console.log(obj instanceof Human) 
}
17
Q

What are higher order functions

A

Higher-Order functions accept functions as parameters or return a function as an output

18
Q

Currying

A

The process of transforming a function to treat its parameters as a sequence of individual function calls that each take one parameter. For example, func(a, b, c) would become func(a)(b)(c).

Currying is achieved by creating functions that return other functions, taking advantage of closures. For example, a curried sum function would look like this:

function curriedSum(a) {
return function(b) {
return a + b;
};
}
This could then be used to create partial versions of this function, for example an “add four” function:

const addFour = curriedSum(4);
addFour(10); // 14

19
Q

Arrow function and normal function difference

A

Do not have this
Do not have arguments
Can’t be called with super
Don’t have super

20
Q

async programming with setTimeout

A
// Function that returns a promise which resolves after the specified delay
function delay(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

// Asynchronous function using async/await
async function performAsyncOperation() {
  console.log('Starting async operation...');
  await delay(3000); // Waits for 3 seconds
  console.log('Async operation complete!');
}

// Function to be used as a callback
function callbackExample() {
  console.log('This is a callback example executed after 2 seconds');
}

// Using setTimeout with a callback
setTimeout(callbackExample, 2000);

// Execute the asynchronous function
performAsyncOperation();
20
Q

cookie

A
// to set the cookie value, cookie values get added automatically one after another with ;
document.cookie='name=harsh';

// setting this will delete the cookie
document.cookie='name=harsh; max-age=0';
21
Q

Web socket

A
    // Create a new WebSocket connection
    const socket = new WebSocket('ws://localhost:8080', token);

    // Handle connection open event
    socket.addEventListener('open', function (event) {
      console.log('Connected to the WebSocket server');
      socket.send('Hello Server!');
    });

    // Handle messages received from the server
    socket.addEventListener('message', function (event) {
      console.log('Message from server:', event.data);
    });

    // Handle connection close event
    socket.addEventListener('close', function (event) {
      console.log('Disconnected from the WebSocket server');
    });

    // Send a message to the server when the button is clicked

other events:
close
error

22
Q

Web components

A

Custom elements – to define custom HTML elements.
Shadow DOM – to create an internal DOM for the component, hidden from the others.
CSS Scoping – to declare styles that only apply inside the Shadow DOM of the component.
Event retargeting and other minor stuff to make custom components better fit the development.

class MyElement extends HTMLElement {
  constructor() {
    super();
    // element created
  }

  connectedCallback() {
    // browser calls this method when the element is added to the document
    // (can be called many times if an element is repeatedly added/removed)
  }

  disconnectedCallback() {
    // browser calls this method when the element is removed from the document
    // (can be called many times if an element is repeatedly added/removed)
  }

  static get observedAttributes() {
    return [/* array of attribute names to monitor for changes */];
  }

  attributeChangedCallback(name, oldValue, newValue) {
    // called when one of attributes listed above is modified
  }

  adoptedCallback() {
    // called when the element is moved to a new document
    // (happens in document.adoptNode, very rarely used)
  }

  // there can be other element methods and properties
}
// let the browser know that <my-element> is served by our new class
customElements.define("my-element", MyElement);

Customise built in components

<script>
// The button that says "hello" on click
class HelloButton extends HTMLButtonElement {
  constructor() {
    super();
    this.addEventListener('click', () => alert("Hello!"));
  }
}

customElements.define('hello-button', HelloButton, {extends: 'button'});
</script>

<button is="hello-button">Click me</button>

<button is="hello-button" disabled>Disabled</button>
customElements.define('show-hello', class extends HTMLElement {
  connectedCallback() {
    const shadow = this.attachShadow({mode: 'open'});
    shadow.innerHTML = `<p>
      Hello, ${this.getAttribute('name')}
    </p>`;
  }
});
23
Q

Cancellable promise

A

simple solution

function cancellablePromise(promise) {
  let rejectFn = null;

  const wrapper = new Promise((resolve, reject) => {
    rejectFn = reject;

    promise.then(resolve)
      .catch(reject)
  });

  wrapper.cancel = function() {
    rejectFn({
      isCancelled: true
    });
  }

  return wrapper;
}

const pro = cancellablePromise(new Promise((res, rej) => {
	res(1);
}));

pro.then(console.log)
pro.catch(console.log)
/* pro.cancel(); */

correct solution

class CancellablePromise extends Promise {
  constructor(executor) {
    let _reject;

    super((resolve, reject) => {
      _reject = reject;
      executor(resolve, reject);
    });

    this._reject = _reject;
  }

  cancel() {
    this._reject('Promise cancelled');
  }
}

// Usage example:
const longRunningTask = new CancellablePromise((resolve, reject) => {
  const timerId = setTimeout(() => {
    resolve('Task completed');
  }, 5000);
});

// To cancel the promise:
longRunningTask.cancel();

// To use the promise:
longRunningTask
  .then(result => console.log(result))
  .catch(error => console.error(error));
24
Q

encryption and decryption in js

A

using cryptojs

function encrypt(message, secretKey) {
  const ciphertext = CryptoJS.AES.encrypt(message, secretKey).toString();
  return ciphertext;
}

// Decryption function
function decrypt(ciphertext, secretKey) {
  const bytes = CryptoJS.AES.decrypt(ciphertext, secretKey);
  const originalText = bytes.toString(CryptoJS.enc.Utf8);
  return originalText;
}

// Example usage
const secretKey = "mySecretKey12#\$\$\$\$$GGG";
const message = "Hello, World!";

console.log("Original message:", message);

const encrypted = encrypt(message, secretKey);
console.log("Encrypted:", encrypted);

const decrypted = decrypt(encrypted, secretKey);
console.log("Decrypted:", decrypted);

using inbuilt crypto module
Required things
1. iv from uint8Array
2. generated key - type of algo, length
3. encrypt, decrypt

const iv = crypto.getRandomValues(new Uint8Array(16));

async function generateKey() {
  return crypto.subtle.generateKey({
      name: 'AES-CBC',
      length: 256,
    },
    true,
    ['encrypt', 'decrypt']
  );
}

async function encrypt(text, key) {
  const encodedText = new TextEncoder().encode(text);
  
  const cipherText = await crypto.subtle.encrypt({
  	name:'AES-CBC',
    iv
  }, key, encodedText);
  
  return new Uint8Array(cipherText);
}

async function decrypt(encryptedValue, key) {
	 const plainText = await crypto.subtle.decrypt({
  	name:'AES-CBC',
    iv
  }, key, encryptedValue.buffer);
  
  return new TextDecoder().decode(plainText);
}

async function run() {
  try {
    const key = await generateKey();
    const encryptedText = await encrypt('harsh', key);
    const decryptedText = await decrypt(encryptedText, key);
    console.log(decryptedText);
  } catch (error) {
    console.log(error);
  }
}

run();
25
Q

File upload js

A
<form id="myForm">
  <input type="text" name="username" placeholder="Username"><br>
  <input type="email" name="email" placeholder="Email"><br>
  <input type="file" name="file"><br>
  <button type="submit">Submit</button>
</form>

document.getElementById('myForm').addEventListener('submit', function(event) {
    event.preventDefault(); // Prevent the default form submission

    const formData = new FormData(this); // 'this' refers to the form element

    fetch('/submit', {
        method: 'POST',
        body: formData,
    })
    .then(response => response.json())
    .then(data => {
        console.log('Success:', data);
    })
    .catch((error) => {
        console.error('Error:', error);
    });
});

with progress

document.getElementById('myForm').addEventListener('submit', function(event) {
    event.preventDefault(); // Prevent the default form submission

    const formData = new FormData(this); // 'this' refers to the form element
    const xhr = new XMLHttpRequest(); // Create a new instance

    // Set up the request
    xhr.open('POST', '/submit');

    // Progress listener
    xhr.upload.addEventListener('progress', function(e) {
        if (e.lengthComputable) {
            const percentComplete = (e.loaded / e.total) * 100;
            document.getElementById('uploadProgress').value = percentComplete;
            console.log('Upload progress: ' + percentComplete + '%');
        }
    });

    // Load listener
    xhr.addEventListener('load', function(e) {
        if (xhr.status === 200) {
            console.log('Upload complete:', xhr.responseText);
        } else {
            console.error('Upload failed:', xhr.statusText);
        }
    });

    // Error listener
    xhr.addEventListener('error', function(e) {
        console.error('Error:', xhr.statusText);
    });

    // Send the form data
    xhr.send(formData);
});
26
Q

deep clone in js

A

JSON.parse(JSON.stringify())

function deepClone(obj) {
    // Handle primitive types and null
    if (obj === null || typeof obj !== 'object') {
        return obj;
    }

    // Handle Date
    if (obj instanceof Date) {
        return new Date(obj.getTime());
    }

    // Handle Array
    if (Array.isArray(obj)) {
        return obj.map(item => deepClone(item));
    }

    // Handle Object
    if (obj instanceof Object) {
        let copy = {};
        for (let key in obj) {
            if (obj.hasOwnProperty(key)) {
                copy[key] = deepClone(obj[key]);
            }
        }
        return copy;
    }

    throw new Error("Unable to copy obj! Its type isn't supported.");
}

// Example usage
const originalObject = {
    a: 1,
    b: {
        c: 2,
        d: [3, 4, { e: 5 }]
    },
    f: new Date(),
    g: /hello/g
};

const clonedObject = deepClone(originalObject);

console.log(clonedObject);
console.log(clonedObject.b.d[2] === originalObject.b.d[2]); // false
console.log(clonedObject.f instanceof Date); // true
console.log(clonedObject.g instanceof RegExp); // true
27
Q

custom stringify

A
function customStringify(obj) {
    if (obj === null) return 'null';
    if (typeof obj === 'undefined') return 'undefined';
    if (typeof obj === 'string') return `"${obj}"`;
    if (typeof obj === 'number' || typeof obj === 'boolean') return String(obj);
    if (typeof obj === 'function') return undefined;    
    
    if (Array.isArray(obj)) {
        const elements = obj
            .map(element => customStringify(element))
            .filter(element => element !== undefined);
        if (elements.length === 0) return '[]';
        return `[${elements.join(`,`)}]`;
    }
    
    if (typeof obj === 'object') {
        const properties = Object.keys(obj)
            .map(key => {
                const value = customStringify(obj[key]);
                if (value === undefined) return undefined;
                return `"${key}":${value}`;
            })
            .filter(prop => prop !== undefined);
        if (properties.length === 0) return '{}';
        return `{${properties.join(`,`)}}`;
    }
}

// Example usage
const testObject = {
    name: "John Doe",
    age: 30,
    isStudent: false,
    grades: [95, 87, 92],
    address: {
        street: "123 Main St",
        city: "Anytown"
    },
    sayHello: function() { console.log("Hello!"); }
};

console.log(customStringify(testObject));
console.log(JSON.stringify(testObject)); // Compare with built-in JSON.stringify
28
Q

custom parse

A
function parseJSON(jsonString) {
    // Check if input is a string
    if (typeof jsonString !== 'string') {
        throw new Error('Input must be a string');
    }

    // Remove whitespace from beginning and end of string
    jsonString = jsonString.trim();

    // Helper function to parse value
    function parseValue() {
        if (jsonString[0] === '{') {
            return parseObject();
        } else if (jsonString[0] === '[') {
            return parseArray();
        } else if (jsonString[0] === '"') {
            return parseString();
        } else if (jsonString[0] === 't' || jsonString[0] === 'f') {
            return parseBoolean();
        } else if (jsonString[0] === 'n') {
            return parseNull();
        } else {
            return parseNumber();
        }
    }

    // Helper function to parse object
    function parseObject() {
        let result = {};
        jsonString = jsonString.slice(1).trim(); // Remove '{'

        while (jsonString[0] !== '}') {
            let key = parseString();
            jsonString = jsonString.slice(1).trim(); // Remove ':'
            let value = parseValue();
            result[key] = value;

            if (jsonString[0] === ',') {
                jsonString = jsonString.slice(1).trim(); // Remove ','
            }
        }

        jsonString = jsonString.slice(1).trim(); // Remove '}'
        return result;
    }

    // Helper function to parse array
    function parseArray() {
        let result = [];
        jsonString = jsonString.slice(1).trim(); // Remove '['

        while (jsonString[0] !== ']') {
            let value = parseValue();
            result.push(value);

            if (jsonString[0] === ',') {
                jsonString = jsonString.slice(1).trim(); // Remove ','
            }
        }

        jsonString = jsonString.slice(1).trim(); // Remove ']'
        return result;
    }

    // Helper function to parse string
    function parseString() {
        let result = '';
        jsonString = jsonString.slice(1); // Remove '"'

        while (jsonString[0] !== '"') {
            result += jsonString[0];
            jsonString = jsonString.slice(1);
        }

        jsonString = jsonString.slice(1).trim(); // Remove '"'
        return result;
    }

    // Helper function to parse number
    function parseNumber() {
        let numString = '';

        while (jsonString[0] >= '0' && jsonString[0] <= '9' || jsonString[0] === '.' || jsonString[0] === '-') {
            numString += jsonString[0];
            jsonString = jsonString.slice(1);
        }

        return parseFloat(numString);
    }

    // Helper function to parse boolean
    function parseBoolean() {
        if (jsonString.startsWith('true')) {
            jsonString = jsonString.slice(4).trim(); // Remove 'true'
            return true;
        } else if (jsonString.startsWith('false')) {
            jsonString = jsonString.slice(5).trim(); // Remove 'false'
            return false;
        }
    }

    // Helper function to parse null
    function parseNull() {
        if (jsonString.startsWith('null')) {
            jsonString = jsonString.slice(4).trim(); // Remove 'null'
            return null;
        }
    }

    // Parse the input JSON string and return the resulting value
    return parseValue();
}

// Example usage
const jsonString = '{"name": {"firstName":"John", "lastName":"test"}, "age": 30, "isStudent": false}';
const jsonObj = parseJSON(jsonString);
console.log(jsonObj);
29
Q

Flat array

A
Array.prototype.customFlat = function(depth = 1) {
    const flatArray = (array, depth) => {
        let result = [];
        
        array.forEach(item => {
            if (Array.isArray(item) && depth > 0) {
                result = result.concat(flatArray(item, depth - 1));
            } else {
                result.push(item);
            }
        });
        
        return result;
    };
    
    return flatArray(this, depth);
};

// Example usage
const nestedArray = [1, [2, [3, [4, 5]]]];
console.log(nestedArray.customFlat(2)); // [1, 2, 3, [4, 5]]