├── README.md └── sections ├── polyfill └── README.md ├── problem-solving └── README.md └── this └── README.md /README.md: -------------------------------------------------------------------------------- 1 | # js-interview-preparation 2 | 3 | This is a preparation guide for your next JavaScript Interview. You will learn some essential concepts that will help you to understand JS as well as pass interviews. 4 | 5 | ### Table of Contents 6 | 7 |
8 | 9 | Expand Table of Contents 10 | 11 | - [Section 1: this keyword](#section-1-this-keyword) 12 | - [Section 2: Bind, Call and Apply](#section-2-bind-call-and-apply) 13 | - [Section 3: ProtoType](#section-3-prototype) 14 | - [Section 4: Function](#section-4-function) 15 | - [Section 5: Hoisting] 16 | - [Section 6: Closure] 17 | - [Section 7: Problem Solving](#section-7-problem-solving) 18 | - [Section 8: Polyfill](#section-8-polyfill) 19 | 20 |
21 | 22 | # Section 1: this keyword 23 | 24 | In JavaScript this keyword means reference of its context. 25 | 26 | ## this inside global or window object 27 | 28 | ```js 29 | console.log(this); 30 | // window { 0: global, window: Window } 31 | ``` 32 | 33 | 🔗 [**Learn More**](./sections/this/README.md) 34 | 35 | # Section 2: Bind, Call and Apply 36 | 37 | ```js 38 | const person = { 39 | firstName: "John", 40 | lastName: "Doe", 41 | fullName: function () { 42 | return this.firstName + " " + this.lastName; 43 | }, 44 | }; 45 | 46 | const member = { 47 | firstName: "Muhammad", 48 | lastName: "Lahin", 49 | }; 50 | 51 | let fullName = person.fullName.bind(member); 52 | fullName(); // Muhammad Lahin 53 | ``` 54 | 55 | .bind() method creates a new function called fullName(), and change the person object's this context to newly created member object's this context. 56 | 57 | ```js 58 | const person = { 59 | firstName: "John", 60 | lastName: "Doe", 61 | fullName: function (age) { 62 | return `${this.firstName} ${this.lastName} age is ${age}`; 63 | }, 64 | }; 65 | 66 | const member = { 67 | firstName: "Muhammad", 68 | lastName: "Lahin", 69 | }; 70 | 71 | person.fullName.call(member, 24); // Muhammad Lahin age is 24 72 | ``` 73 | 74 | .call() method calls a function with a given this context value and arguments provided individually. 75 | 76 | ```js 77 | const person = { 78 | firstName: "John", 79 | lastName: "Doe", 80 | fullName: function (age, birthYear) { 81 | return `${this.firstName} ${this.lastName} age is ${age} birth year is ${birthYear}`; 82 | }, 83 | }; 84 | 85 | const member = { 86 | firstName: "Muhammad", 87 | lastName: "Lahin", 88 | }; 89 | 90 | person.fullName.apply(member, [24, 1994]); // Muhammad Lahin age is 24 birth year is 1994 91 | ``` 92 | 93 | .apply() method invokes the function on given context and allows to pass arguments as an array. 94 | 95 | In general Call and Apply both are similar only difference is the way they get arguments. 96 | 97 | # Section 3: ProtoType 98 | 99 | ## What is ProtoType? 100 | 101 | Each Object and Array contains a property or object called [[Prototype]]. Which indicated to the prototype of that object, this can be null or points to another object. 102 | 103 | ## What is `__proto__`? 104 | 105 | [[Prototype]] is an internal property that cannot be accessed directly, so we have `__proto__` in order to access that prototype. 106 | 107 | # Section 4: Function 108 | 109 | ## Function Statement 110 | 111 | If function starts with function keyword then this is Function Statement. 112 | 113 | ```js 114 | function add(a, b) {} 115 | ``` 116 | 117 | ## Function Expression 118 | 119 | You can assign function into variable and this is Function Expression. 120 | 121 | ```js 122 | const add = function (a, b) {}; 123 | ``` 124 | 125 | ## Difference between Function Statement & Function Expression 126 | 127 | The difference between them is Hoisting. 128 | 129 | # Section 7: Problem Solving 130 | 131 | ## Check if a string is Pangram or not 132 | 133 | Means if string consist 26 english alphabets or not. 134 | 135 | ```js 136 | const str = "The quick brown fox jumps over the lazy dog"; 137 | 138 | function isPangram(text) { 139 | const tracks = new Array(26).fill(false); 140 | let index; 141 | 142 | for (let i = 0; i < text.length; i++) { 143 | if (text[i] >= "A" && text[i] <= "Z") { 144 | index = text.charCodeAt(i) - "A".charCodeAt(0); 145 | } else if (text[i] >= "a" && text[i] <= "z") { 146 | index = text.charCodeAt(i) - "a".charCodeAt(0); 147 | } 148 | 149 | tracks[index] = true; 150 | } 151 | 152 | return tracks.every((track) => track === true); 153 | } 154 | 155 | console.log(isPangram(str)); // true 156 | ``` 157 | 158 | 🔗 [**Learn More**](./sections/problem-solving/README.md) 159 | 160 | # Section 8: Polyfill 161 | 162 | ## .map() polyfill 163 | 164 | ```js 165 | Array.prototype.myMap = function (cb) { 166 | 167 | let temp = []; 168 | 169 | for(let index = 0; index < this.length; index++) { // this - is the actual object that is currently attached with myMap parent 170 | temp.push(cb(this[index], index); 171 | } 172 | 173 | return temp; 174 | 175 | } 176 | 177 | const arr = [1, 2, 3]; 178 | const res = arr.myMap(item => item * 2); 179 | 180 | console.log(res); // [2, 4, 6] 181 | ``` 182 | 183 | 🔗 [**Learn More**](./sections/polyfill/README.md) 184 | -------------------------------------------------------------------------------- /sections/polyfill/README.md: -------------------------------------------------------------------------------- 1 | # Polyfill 2 | 3 | ## .filter() polyfill 4 | 5 | ```js 6 | Array.prototype.myFilter = function (cb) { 7 | const temp = []; 8 | 9 | for (let index = 0; index < this.length; index++) { 10 | if (cb(this[index], index)) temp.push(this[index]); 11 | } 12 | 13 | return temp; 14 | }; 15 | 16 | const arr = [1, 2, 3]; 17 | const res = arr.myFilter((item) => item < 2); 18 | 19 | console.log(res); // [1] 20 | ``` 21 | 22 | ## .reduce() polyfill 23 | 24 | ```js 25 | Array.prototype.myReduce = function (cb, initialValue) { 26 | let accumulator = initialValue; 27 | 28 | for (let index = 0; index < this.length; index++) { 29 | accumulator = cb(accumulator, this[index]); 30 | } 31 | 32 | return accumulator; 33 | }; 34 | 35 | const arr = [1, 2, 3]; 36 | 37 | const res = arr.myReduce((accumulator, current) => accumulator + current, 0); 38 | console.log(res); // 6 39 | ``` 40 | 41 | ## promise.all() polyfill 42 | 43 | ```js 44 | function task1() { 45 | return new Promise((resolve, reject) => { 46 | setTimeout(() => { 47 | resolve("Task one resolved"); 48 | }, 1000); 49 | }); 50 | } 51 | 52 | function task2() { 53 | return new Promise((resolve, reject) => { 54 | setTimeout(() => { 55 | resolve("Task two resolved"); 56 | }, 2000); 57 | }); 58 | } 59 | 60 | myAllPromise([task1, task2]) 61 | .then((response) => console.log(response)) 62 | .catch((err) => console.log(err)); 63 | 64 | function myAllPromise(tasks) { 65 | const results = []; 66 | let countResolved = 0; 67 | 68 | return new Promise((resolve, reject) => { 69 | tasks.forEach((task, index) => { 70 | task() 71 | .then((resp) => { 72 | results.push(resp); 73 | countResolved++; 74 | 75 | if (countResolved === tasks.length) { 76 | resolve(results); 77 | } 78 | }) 79 | .catch((err) => { 80 | reject(err); 81 | }); 82 | }); 83 | }); 84 | } 85 | ``` 86 | 87 | ## promise.allSettled() polyfill 88 | 89 | ```js 90 | function task1() { 91 | return new Promise((resolve, reject) => { 92 | setTimeout(() => { 93 | resolve("Task one resolved"); 94 | }, 1000); 95 | }); 96 | } 97 | 98 | function task2() { 99 | return new Promise((resolve, reject) => { 100 | setTimeout(() => { 101 | reject("Task two rejected"); 102 | }, 1000); 103 | }); 104 | } 105 | 106 | myAllSettledPromise([task1, task2]) 107 | .then((response) => console.log(response)) 108 | .catch((err) => console.log(err)); 109 | 110 | function myAllSettledPromise(tasks) { 111 | const results = []; 112 | let count = 0; 113 | 114 | return new Promise((resolve, reject) => { 115 | tasks.forEach((task, index) => { 116 | task() 117 | .then((resp) => { 118 | results.push(resp); 119 | count++; 120 | if (count === tasks.length) { 121 | resolve(results); 122 | } 123 | }) 124 | .catch((err) => { 125 | results.push(err); 126 | count++; 127 | if (count === tasks.length) { 128 | resolve(results); 129 | } 130 | }); 131 | }); 132 | }); 133 | } 134 | ``` 135 | 136 | ## .bind() polyfill 137 | 138 | ```js 139 | const user = { 140 | name: "lahin", 141 | age: 30, 142 | getInfo() { 143 | return this.name + " " + this.age; 144 | }, 145 | }; 146 | 147 | const new_user = { 148 | name: "hussain", 149 | age: 40, 150 | }; 151 | 152 | Function.prototype.myBind = function (scope, ...args) { 153 | scope._this = this; 154 | 155 | return function () { 156 | return scope._this(...args); 157 | }; 158 | }; 159 | 160 | const result = user.getInfo.myBind(new_user); 161 | console.log(result()); // hussain 40 162 | ``` 163 | -------------------------------------------------------------------------------- /sections/problem-solving/README.md: -------------------------------------------------------------------------------- 1 | # Problem Solving 2 | 3 | ## Check two strings anagram or not 4 | 5 | ```js 6 | const value1 = "Hussain"; 7 | const value2 = "rumhnee"; 8 | 9 | const checkAnagram = (str1, str2) => { 10 | let sort1 = str1.split("").sort().join(""); 11 | let sort2 = str2.split("").sort().join(""); 12 | 13 | if (sort1 !== sort2) { 14 | return false; 15 | } 16 | 17 | return true; 18 | }; 19 | 20 | console.log(checkAnagram(value1, value2)); // true 21 | ``` 22 | 23 | ## Create a Debounce Function 24 | 25 | ```js 26 | function debounce(fn, delay) { 27 | let timer; 28 | return function () { 29 | if (timer) { 30 | clearTimeout(timer); 31 | } 32 | timer = setTimeout(() => { 33 | fn(); 34 | }, delay); 35 | }; 36 | } 37 | ``` 38 | 39 | ## Find the Longest Consecutive Charecter in a given string 40 | 41 | ```js 42 | const longestConsecutiveChar = (str) => { 43 | let track = { char: "", count: 0 }; 44 | let result = { chat: "", count: 0 }; 45 | 46 | for (let i = 0; i < str.length; i++) { 47 | if (track.char !== str[i]) { 48 | track.char = str[i]; 49 | track.count = 1; 50 | } else if (track.char === str[i]) { 51 | track.count++; 52 | } 53 | 54 | if (track.count > result.count) { 55 | result = { ...track }; 56 | } 57 | } 58 | 59 | return result.char; 60 | }; 61 | 62 | console.log(longestConsecutiveChar("aabbb")); // b 63 | console.log(longestConsecutiveChar("aaabb")); // a 64 | ``` 65 | 66 | ## Find if a string contains duplicate or not 67 | 68 | ```js 69 | const isDuplicate = (str) => { 70 | const map = new Map(); 71 | 72 | for (let item of str) { 73 | if (map.has(item)) { // the time complexity for .has is O(1) 74 | return true; 75 | } 76 | map.set(item, true); 77 | } 78 | 79 | return false; 80 | }; 81 | 82 | console.log(isDuplicate("11223")); // true 83 | console.log(isDuplicate("12345")); // false 84 | ``` 85 | 86 | ## Two Sum 87 | 88 | Given an array of integers nums and an integer target, return indices of the two numbers such that they add up to target. 89 | 90 | Input: nums = [2,7,11,15], target = 9 91 | 92 | Output: [0,1] 93 | 94 | ```js 95 | function twoSum(arr, target) { 96 | let track = {}; 97 | let res = null; 98 | 99 | for (let i = 0; i < arr.length; i++) { 100 | let sub = target - arr[i]; 101 | 102 | if (track.hasOwnProperty(arr[i])) { 103 | res = [track[arr[i]], i]; 104 | break; 105 | } 106 | 107 | track[sub] = i; 108 | } 109 | 110 | return res; 111 | } 112 | 113 | console.log(twoSum([2,7,11,15], 9)); // [0, 1] 114 | ``` 115 | 116 | ## Retry API after a specific type 117 | 118 | ```js 119 | const makeRandom = (min, max) => 120 | Math.floor(Math.random() * (max - min + 1)) + min; 121 | 122 | const retryAPI = (fetcher, maxRetryCount) => { 123 | return new Promise((resolve, reject) => { 124 | let retries = 0; 125 | const caller = () => { 126 | fetcher("lahin31") 127 | .then((data) => { 128 | resolve(data); 129 | }) 130 | .catch((err) => { 131 | if (retries < maxRetryCount) { 132 | retries++; 133 | 134 | const retryAfter = makeRandom(1000, 5000); 135 | 136 | setTimeout(() => { 137 | console.log("Retrying in " + retryAfter + " seconds"); 138 | 139 | caller(); 140 | }, retryAfter); 141 | } else { 142 | reject(err); 143 | } 144 | }); 145 | }; 146 | retries = 1; 147 | caller(); 148 | }); 149 | }; 150 | 151 | const fetchGithub = async (username) => { 152 | const response = await fetch(`https://api.github.com/users/${username}`); 153 | const data = await response.json(); 154 | return data; 155 | }; 156 | 157 | retryAPI(fetchGithub, 5); 158 | ``` 159 | ## Clear all timeouts generated by setTimeout 160 | 161 | First we took an array that stores the result generated by setTimeout, to store that we need to make a make a reference of original setTimeout. Then we need to modify setTimeout & clearTimeout. 162 | 163 | ```js 164 | 165 | window.timeoutResults = []; 166 | 167 | const originalTimeoutFn = window.setTimeout; 168 | 169 | window.setTimeout = function(fn, delay) { 170 | const result = originalTimeoutFn(fn, delay); 171 | 172 | timeoutResults.push(result); 173 | 174 | return result; 175 | } 176 | 177 | window.clearTimeout = function() { 178 | while(timeoutResults.length) { 179 | clearTimeout(timeoutResults.pop()); 180 | } 181 | } 182 | 183 | window.setTimeout(() => {console.log("React")}, 1000); 184 | window.setTimeout(() => {console.log("Angular")}, 2000); 185 | window.setTimeout(() => {console.log("Vue")}, 3000); 186 | 187 | window.clearTimeout(); 188 | ``` -------------------------------------------------------------------------------- /sections/this/README.md: -------------------------------------------------------------------------------- 1 | # this keyword 2 | 3 | ## this inside regular function 4 | 5 | ```js 6 | function doSomething() { 7 | this.name = "Hussain"; 8 | console.log(this); 9 | } 10 | 11 | doSomething(); 12 | // window { 0: global, window: Window, name: Hussain, ... } 13 | ``` 14 | 15 | The parent scope of `doSomething` function is the window object. 16 | 17 | ## this inside Arrow Function 18 | 19 | ```js 20 | const doSomething = () => { 21 | this.name = "Hussain"; 22 | console.log(this); // { name: Hussain } 23 | }; 24 | 25 | doSomething(); 26 | ``` 27 | 28 | Since doSomething() is an Arrow Function and we are providing this (this.name) inside of it so it will work based on this context. 29 | 30 | ```js 31 | this.name = "Hussain"; 32 | const doSomething = () => { 33 | console.log(this); // { name: 'Hussain' } 34 | }; 35 | 36 | console.log(this); // { name: 'Hussain' } 37 | 38 | doSomething(); 39 | ``` 40 | 41 | If we don't provide any this environment inside `doSomething` function this will go up to its parent context and grab its this. 42 | 43 | ## this inside object 44 | 45 | example 1: 46 | 47 | ```js 48 | const user = { 49 | name: "Lahin", 50 | age: 30, 51 | getInfo() { 52 | return `Name is ${this.name} and Age is ${this.age}`; 53 | }, 54 | }; 55 | 56 | console.log(user.getInfo()); // Name is Lahin and Age is 30 57 | ``` 58 | 59 | example 2: 60 | 61 | ```js 62 | const user = { 63 | name: "Lahin", 64 | age: 30, 65 | education: { 66 | university: "Metropolitan University", 67 | getInfo() { 68 | return `${this.name} and your university is ${this.university}`; 69 | }, 70 | }, 71 | }; 72 | 73 | console.log(user.education.getInfo()); // undefined and your university is Metropolitan University 74 | ``` 75 | 76 | `getInfo()` has a parent "this" context inside `education` object not in `user` object thats why this.name is undefined. 77 | --------------------------------------------------------------------------------