├── LICENSE ├── README.md ├── flatten-array └── index.js ├── impement-array-reduce ├── README.md └── index.js ├── implement-array-every ├── README.md └── index.js ├── implement-array-filter ├── README.md └── index.js ├── implement-array-foreach ├── README.md └── index.js ├── implement-array-map ├── README.md └── index.js ├── implement-async-parallel └── index.js ├── implement-async-series └── index.js ├── implement-bind ├── README.md └── index.js └── implement-promise-all └── index.js /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Nitish Phanse 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # annoying-js-interview 2 | List of Questions people have been asked in JS interviews. 3 | 4 | ## Some annoying Questions 5 | 6 | - Implement array.map ✅ 7 | - Implement array.filter ✅ 8 | - Implement array.forEach ✅ 9 | - implement array.Every 10 | - implement array.some 11 | - implement array.find 12 | - implement Fn.bind using call and apply 13 | - implement Async Series 14 | - implement Async parallel 15 | - Implement memoisation 16 | - Using array reduce implement map 17 | - using array reduce implement filter 18 | - Implement an Event listener on array for push and pop 19 | - implement Promise.all 20 | - Binary Search 21 | - Implement a ticker component 22 | - Loader Question 23 | - Flatten an Array 24 | -------------------------------------------------------------------------------- /flatten-array/index.js: -------------------------------------------------------------------------------- 1 | Array.prototype.flatten = function () { 2 | let flatArray = [] 3 | for (let index = 0; index < this.length; index++) { 4 | const element = this[index]; 5 | if (Array.isArray(element)) { 6 | flatArray = flatArray.concat(this.flatten.call(element)) 7 | } else { 8 | flatArray.push(element) 9 | } 10 | } 11 | 12 | return flatArray; 13 | } 14 | 15 | // function flatten 16 | 17 | 18 | 19 | //const nestedArr = [[1], [[1, 4, [5, 3]], [1, 2, 3, 4]]] => [1, 1, 4, 5, 3, 1, 2, 3, 4] 20 | 21 | const nestedArr = [[1], [[1, 4, [5, 3]], [1, 2, 3, [3, 4, [2, [22, [3, 4, 5, 6, 5, [2]]]]], 4]]] 22 | //const nestedArr = [1, 2, 3, 4, [1]] 23 | 24 | const flat = nestedArr.flatten(); 25 | console.log(flat); -------------------------------------------------------------------------------- /impement-array-reduce/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nitish24p/annoying-js-interview/ae5157e463168692987a9ee12731260deca9da09/impement-array-reduce/README.md -------------------------------------------------------------------------------- /impement-array-reduce/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Reduce function is attached to the array prototype 3 | * It takes in a callback and passes every item in the array 4 | * through the callback, and also a starting value 5 | */ 6 | 7 | /** 8 | * The callback gets 3 arguments 9 | * the item, the index and the execution context 10 | * 11 | */ 12 | Array.prototype.newReduce = function (callback, startingValue) { 13 | // as starting value is an optional param 14 | // make a check 15 | let accumulator = startingValue || undefined; 16 | for (let index = 0; index < this.length; index++) { 17 | if (accumulator) { 18 | accumulator = callback.call(accumulator, accumulator, this[index], index, this) 19 | } else { 20 | accumulator = this[index] 21 | } 22 | } 23 | 24 | return accumulator; 25 | } 26 | 27 | const nums = [1, 2, 3, 4, 5] 28 | const sum = nums.newReduce((accum, current) => { 29 | accum.push(current * 2) 30 | return accum 31 | }, []); 32 | console.log(sum) 33 | 34 | const queryString = "cat=meow&duck=quack&dog=woof"; 35 | 36 | const queryObject = queryString.split("&").newReduce((accum, current) => { 37 | const splitString = current.split("=") 38 | accum[splitString[0]] = splitString[1]; 39 | return accum; 40 | }, {}) 41 | 42 | console.log(queryObject); -------------------------------------------------------------------------------- /implement-array-every/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nitish24p/annoying-js-interview/ae5157e463168692987a9ee12731260deca9da09/implement-array-every/README.md -------------------------------------------------------------------------------- /implement-array-every/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Every function is attached to the array prototype 3 | * It takes in a callback and passes every item in the array 4 | * through the callback 5 | */ 6 | 7 | /** 8 | * The callback gets 3 arguments 9 | * the item, the index and the execution context 10 | * 11 | */ 12 | Array.prototype.newEvery = function (callback, context) { 13 | // as starting value is an optional param 14 | // make a check 15 | for (let index = 0; index < this.length; index++) { 16 | if (!callback.call(context, this[index], index, this)) 17 | return false 18 | } 19 | 20 | return true 21 | } 22 | 23 | const nums = [1, 2, 3, 4, 5] 24 | const isLessThanSix = nums.newEvery((item, current) => item > 6); 25 | console.log(isLessThanSix) 26 | -------------------------------------------------------------------------------- /implement-array-filter/README.md: -------------------------------------------------------------------------------- 1 | ## Implement Array.filter 2 | 3 | 4 | [Array.filter]("https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter") 5 | 6 | >The filter() method creates a new array with all elements that pass the test implemented by the provided function. 7 | 8 | ### Question 9 | Implement the `Array.filter` method 10 | 11 | ### Thought process Pseudocode 12 | 1. A function which takes a function as an argument and an optional parameter for execution context 13 | 2. The function argument must be passed the array index, the item and the context 14 | 3. The result of the callback invokation is tested, if true the array element is pushed to a new array item 15 | 16 | ### Solution 17 | ```javascript 18 | /** 19 | * Filter function is attached to the array prototype 20 | * It takes in 3 parameters, callback and a context (this) 21 | * argument, the callback is invoked with the current item 22 | * the index, the array, 23 | */ 24 | 25 | /** 26 | * The callback gets 3 arguments 27 | * the item, the index and the execution context 28 | */ 29 | Array.prototype.newFilter = function (callback, context) { 30 | const result = []; 31 | for (let index = 0; index < this.length; index++) { 32 | if (callback.call(context, this[index], index, this)) { 33 | result.push(this[index]) 34 | } 35 | } 36 | 37 | return result 38 | } 39 | 40 | // example 41 | const numbers = [1, 2, 3, 4] 42 | const even = numbers.newFilter(item => item % 2 === 0) 43 | 44 | console.log(even) 45 | 46 | ``` 47 | -------------------------------------------------------------------------------- /implement-array-filter/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Filter function is attached to the array prototype 3 | * It takes in 3 parameters, callback and a context (this) 4 | * argument, the callback is invoked with the current item 5 | * the index, the array 6 | */ 7 | 8 | /** 9 | * The callback gets 3 arguments 10 | * the item, the index and the current array being traversed 11 | */ 12 | Array.prototype.newFilter = function (callback, context) { 13 | const result = []; 14 | for (let index = 0; index < this.length; index++) { 15 | if (callback.call(context, this[index], index, this)) { 16 | result.push(this[index]) 17 | } 18 | } 19 | 20 | return result 21 | } 22 | 23 | // example 24 | const numbers = [1, 2, 3, 4] 25 | const even = numbers.newFilter(item => item % 2 === 0) 26 | 27 | console.log(even) -------------------------------------------------------------------------------- /implement-array-foreach/README.md: -------------------------------------------------------------------------------- 1 | ## Implement Array.forEach 2 | 3 | 4 | [Array.forEach]("https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach") 5 | 6 | >The forEach() method executes a provided function once for each array element. 7 | 8 | ### Question 9 | Implement the `Array.forEach` method 10 | 11 | ### Thought process Pseudocode 12 | 1. A function which takes a function as an argument 13 | 2. The function argument must be passed the array index, the item and the context 14 | 3. A check should me made to see if the item exists in the array 15 | 16 | ### Solution 17 | ```javascript 18 | /** 19 | * Foreach function is attached to the array prototype 20 | * It takes in a callback and passes every item in the array 21 | * through the callback 22 | */ 23 | 24 | /** 25 | * The callback gets 3 arguments 26 | * the item, the index and the execution context 27 | * A for each array loop cannot be broken using break; 28 | */ 29 | Array.prototype.newForEach = function (callback, context) { 30 | for (let index = 0; index < this.length; index++) { 31 | // This is primarily to check if the item 32 | // exists in the array, 33 | if (this.indexOf(this[index]) > -1) { 34 | callback.call(context, this[index], index, this) 35 | } 36 | } 37 | } 38 | 39 | // example 40 | const words = ["adam", "ate", "an", "apple"] 41 | const upperCaseList = [] 42 | words.newForEach((word, index, context) => { 43 | upperCaseList.push(word.toUpperCase()) 44 | }) 45 | 46 | console.log(upperCaseList) 47 | 48 | ``` 49 | 50 | ### Caveat 51 | The for each loop cannot be broken, in between. In such case where the loop must be exited when a condition is met, `Array.some` or `Array.find` me be a better option. -------------------------------------------------------------------------------- /implement-array-foreach/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Foreach function is attached to the array prototype 3 | * It takes in a callback and passes every item in the array 4 | * through the callback 5 | */ 6 | 7 | /** 8 | * The callback gets 3 arguments 9 | * the item, the index and the execution context 10 | * A for each array loop cannot be broken using break; 11 | */ 12 | Array.prototype.newForEach = function (callback, context) { 13 | for (let index = 0; index < this.length; index++) { 14 | // This is primarily to check if the item 15 | // exists in the array, 16 | if (this.indexOf(this[index]) > -1) { 17 | callback.call(context, this[index], index, this) 18 | } 19 | } 20 | } 21 | 22 | // example 23 | const words = ["adam", "ate", "an", "apple"] 24 | const upperCaseList = [] 25 | words.newForEach((word, index, context) => { 26 | upperCaseList.push(word.toUpperCase()) 27 | }) 28 | 29 | console.log(upperCaseList) -------------------------------------------------------------------------------- /implement-array-map/README.md: -------------------------------------------------------------------------------- 1 | ## Implement Array.map 2 | 3 | 4 | [Array.map]("https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map") 5 | 6 | >The map() method creates a new array with the results of calling a provided function on every element in the calling array. 7 | 8 | ### Question 9 | Implement the `Array.map` method 10 | 11 | ### Thought process Pseudocode 12 | 1. A function which takes a function as an argument 13 | 2. The function argument must be passed the array index, the item and the context 14 | 15 | ### Solution 16 | ```javascript 17 | /** 18 | * Map function is attached to the array prototype 19 | * It takes in a callback and passes every item in the array 20 | * through the callback, the result is pushed into a new array 21 | * which is returned 22 | */ 23 | 24 | /** 25 | * The callback gets 3 arguments 26 | * the item, the index and the execution context 27 | */ 28 | Array.prototype.newMap = function (callback) { 29 | const result = []; 30 | for (let index = 0; index < this.length; index++) { 31 | // This is primarily to check if the item 32 | // exists in the array, 33 | if (this.indexOf(this[index]) > -1) { 34 | result[index] = callback(this[index], index, this) 35 | } 36 | } 37 | 38 | return result 39 | } 40 | 41 | // example 42 | const numbers = [1, 2, 3, 4] 43 | numbers[10] = 34; 44 | 45 | const double = numbers.newMap((item, index) => { 46 | return item * 2 47 | }) 48 | 49 | console.log(double) 50 | 51 | ``` 52 | 53 | ### Caveat 54 | The reason for the if condition is basically, to ensure the item is present in the array, `Array.map` does not alter the index of the items in the resultant array, hence in the case above there will be 6 entries which will be emtpty -------------------------------------------------------------------------------- /implement-array-map/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Map function is attached to the array prototype 3 | * It takes in a callback and passes every item in the array 4 | * through the callback, the result is pushed into a new array 5 | * which is returned 6 | */ 7 | 8 | /** 9 | * The callback gets 3 arguments 10 | * the item, the index and the execution context 11 | */ 12 | Array.prototype.newMap = function (callback) { 13 | const result = []; 14 | for (let index = 0; index < this.length; index++) { 15 | // This is primarily to check if the item 16 | // exists in the array, 17 | if (this.indexOf(this[index]) > -1) { 18 | result[index] = callback(this[index], index, this) 19 | } 20 | } 21 | 22 | return result 23 | } 24 | 25 | // example 26 | const numbers = [1, 2, 3, 4] 27 | numbers[10] = 34; 28 | 29 | const double = numbers.newMap((item, index) => { 30 | return item * 2 31 | }) 32 | 33 | console.log(double) -------------------------------------------------------------------------------- /implement-async-parallel/index.js: -------------------------------------------------------------------------------- 1 | function asyncTask() { 2 | const value = Math.floor(Math.random() * 10) 3 | return function (callback) { 4 | setTimeout(() => { 5 | callback(value) 6 | }, value * 1000) 7 | } 8 | 9 | } 10 | 11 | 12 | function asyncParallel(taskList, callback) { 13 | const results = []; 14 | let tasksCompleted = 0; 15 | taskList.forEach(asyncTask => { 16 | asyncTask((value) => { 17 | results.push(value); 18 | tasksCompleted++; 19 | 20 | if (tasksCompleted >= taskList.length) { 21 | callback.call(null, results) 22 | } 23 | }) 24 | }); 25 | } 26 | 27 | const taskList = [ 28 | asyncTask(), 29 | asyncTask(), 30 | asyncTask(), 31 | asyncTask(), 32 | asyncTask(), 33 | asyncTask(), 34 | ] 35 | 36 | asyncParallel(taskList, (result) => { 37 | console.log("got the results", result) 38 | }) -------------------------------------------------------------------------------- /implement-async-series/index.js: -------------------------------------------------------------------------------- 1 | function asyncTask() { 2 | const value = Math.floor(Math.random() * 10) 3 | console.log(value) 4 | return function (callback) { 5 | setTimeout(() => { 6 | callback(value) 7 | }, value * 1000) 8 | } 9 | 10 | } 11 | 12 | 13 | function asyncSeries(taskList, callback) { 14 | var arr = []; 15 | let tasksCompleted = 0; 16 | taskList.reduce((accum, current) => { 17 | return accum.then(someVal => { 18 | return new Promise((resolve, reject) => { 19 | current((value) => { 20 | arr.push(value) 21 | tasksCompleted++ 22 | if (tasksCompleted === taskList.length) { 23 | callback.call(null, arr) 24 | } else { 25 | resolve(value) 26 | } 27 | }) 28 | }) 29 | }) 30 | }, Promise.resolve()) 31 | 32 | } 33 | 34 | const taskList = [ 35 | asyncTask(), 36 | asyncTask(), 37 | 38 | 39 | ] 40 | 41 | asyncSeries(taskList, (result) => { 42 | console.log("got the results", result) 43 | }) -------------------------------------------------------------------------------- /implement-bind/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nitish24p/annoying-js-interview/ae5157e463168692987a9ee12731260deca9da09/implement-bind/README.md -------------------------------------------------------------------------------- /implement-bind/index.js: -------------------------------------------------------------------------------- 1 | Function.prototype.newBind = function (context) { 2 | const currentContext = this; 3 | const currentArguments = Array.prototype.slice.call(arguments, 1); // Dont need the context 4 | return function () { 5 | const args = Array.prototype.slice.call(arguments); 6 | currentContext.apply(context, currentArguments.concat(args)) 7 | } 8 | } 9 | 10 | this.x = 9; // this refers to global "window" object here in the browser 11 | const module = { 12 | x: 81, 13 | getX: function () { return this.x; } 14 | }; 15 | 16 | module.getX(); // 81 17 | 18 | const retrieveX = module.getX; 19 | retrieveX(); 20 | // returns 9 - The function gets invoked at the global scope 21 | 22 | // Create a new function with 'this' bound to module 23 | // New programmers might confuse the 24 | // global const x with module's property x 25 | const boundGetX = retrieveX.bind(module); 26 | console.log(boundGetX()); // 81 -------------------------------------------------------------------------------- /implement-promise-all/index.js: -------------------------------------------------------------------------------- 1 | 2 | function task(time) { 3 | return new Promise(function (resolve, reject) { 4 | setTimeout(function () { 5 | resolve(time); 6 | }, time); 7 | }); 8 | } 9 | 10 | const taskList = [task(1000), task(5000), task(3000)]; 11 | // returns promise with results in an array 12 | 13 | function myPromiseAll(taskList) { 14 | const results = [] 15 | let promisesCompleted = 0; 16 | return new Promise((resolve, reject) => { 17 | taskList.forEach((promise, index) => { 18 | promise.then((val) => { 19 | results[index] = val; 20 | promisesCompleted += 1; 21 | if (promisesCompleted === taskList.length) { 22 | resolve(results) 23 | } 24 | }) 25 | .catch(error => { 26 | reject(error) 27 | }) 28 | }) 29 | }); 30 | } 31 | 32 | myPromiseAll(taskList) 33 | .then(results => { 34 | console.log("got results", results) 35 | }) 36 | .catch(console.error) 37 | --------------------------------------------------------------------------------