Last active
February 24, 2023 09:02
-
-
Save sachinKumarGautam/b5b2a73fc95fc10178763a9d4a202abb to your computer and use it in GitHub Desktop.
This doc includes polyfills for the most common JS functions
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// debounce | |
function debounce(func, wait, immediate) { | |
var timeout; | |
return function() { | |
var context = this, args = arguments; | |
var later = function() { | |
timeout = null; | |
if (!immediate) func.apply(context, args); | |
}; | |
var callNow = immediate && !timeout; | |
clearTimeout(timeout); | |
timeout = setTimeout(later, wait); | |
if (callNow) func.apply(context, args); | |
}; | |
}; | |
// throttle | |
function throttle(func, wait) { | |
// your code here | |
let timer = null; | |
let lastArgs = null; | |
return function(...args) { | |
if(timer) { | |
lastArgs = args; | |
} else { | |
func.apply(this, args); | |
timer = setTimeout(()=>{ | |
if(lastArgs) { | |
func.apply(this,lastArgs); | |
timer = null; | |
} | |
}, wait) | |
} | |
} | |
} | |
// Array map | |
/** | |
* Map function is attached to the array prototype | |
* It takes in a callback and passes every item in the array | |
* through the callback, the result is pushed into a new array | |
* which is returned | |
*/ | |
/** | |
* The callback gets 3 arguments | |
* the item, the index and the execution context | |
*/ | |
Array.prototype.newMap = function (callback) { | |
const result = []; | |
for (let index = 0; index < this.length; index++) { | |
// This is primarily to check if the item | |
// exists in the array, | |
if (this.indexOf(this[index]) > -1) { | |
result[index] = callback(this[index], index, this) | |
} | |
} | |
return result | |
} | |
// Array Filter | |
/** | |
* Filter function is attached to the array prototype | |
* It takes in 3 parameters, callback and a context (this) | |
* argument, the callback is invoked with the current item | |
* the index, the array, | |
*/ | |
/** | |
* The callback gets 3 arguments | |
* the item, the index and the execution context | |
*/ | |
Array.prototype.newFilter = function (callback, context) { | |
const result = []; | |
for (let index = 0; index < this.length; index++) { | |
if (callback.call(context, this[index], index, this)) { | |
result.push(this[index]) | |
} | |
} | |
return result | |
} | |
//Array Reduce | |
/** | |
* Reduce function is attached to the array prototype | |
* It takes in a callback and passes every item, along with accumulator in the array | |
* through the callback, and also a starting value | |
*/ | |
/** | |
* The callback gets 4 arguments | |
* an accumulator, current value, index, current array | |
* | |
*/ | |
Array.prototype.newReduce = function (callback, startingValue) { | |
// as starting value is an optional param | |
// make a check | |
let accumulator = startingValue || undefined; | |
for (let index = 0; index < this.length; index++) { | |
if (accumulator) { | |
accumulator = callback.call(accumulator, accumulator, this[index], index, this) | |
} else { | |
accumulator = this[index] | |
} | |
} | |
return accumulator; | |
} | |
//Array forEach | |
/** | |
* Foreach function is attached to the array prototype | |
* It takes in a callback and passes every item in the array | |
* through the callback | |
*/ | |
/** | |
* The callback gets 3 arguments | |
* the item, the index and the execution context | |
* A for each array loop cannot be broken using break; | |
*/ | |
Array.prototype.newForEach = function (callback, context) { | |
for (let index = 0; index < this.length; index++) { | |
// This is primarily to check if the item | |
// exists in the array, | |
if (this.indexOf(this[index]) > -1) { | |
callback.call(context, this[index], index, this) | |
} | |
} | |
} | |
//Bind | |
Function.prototype.newBind = function (context) { | |
const currentContext = this; | |
const currentArguments = Array.prototype.slice.call(arguments, 1); // Dont need the context | |
return function () { | |
const args = Array.prototype.slice.call(arguments); | |
currentContext.apply(context, currentArguments.concat(args)) | |
} | |
// Async Parallel fucntion | |
// Run the tasks collection of functions in parallel, without waiting until the previous function has completed. If any of the functions pass an error to its callback, the main callback is immediately called with the value of the error. | |
// Question | |
// You have an asyncFunction which takes a callback and the result of the asyncFunction is passed to the callback, create a function asyncParallel which takes an array of asyncFunctions and a resultCallback. When the asyncActions are completed the resultCallback must be invoked with the values. | |
function asyncParallel(taskList, resultsCallback) { | |
const results = []; | |
let tasksCompleted = 0; | |
taskList.forEach(asyncTask => { | |
asyncTask(value => { | |
results.push(value); | |
tasksCompleted++; | |
if (tasksCompleted >= taskList.length) { | |
resultsCallback.call(null, results); | |
} | |
}); | |
}); | |
} | |
const taskList = [ | |
createAsyncTask(), | |
createAsyncTask(), | |
createAsyncTask(), | |
createAsyncTask(), | |
createAsyncTask(), | |
createAsyncTask() | |
]; | |
asyncParallel(taskList, result => { | |
console.log('got the results', result); | |
}); | |
// async series | |
// Run the functions in the tasks collection in series, each one running once the previous function has completed. If any functions in the series pass an error to its callback, no more functions are run, and callback is immediately called with the value of the erro | |
// Question | |
// You have an asyncFunction which takes a callback and the result of the asyncFunction is passed to the callback, create a function asyncSeries which takes an array of asyncFunctions and a resultCallback. asyncSeries should sequentially execute the asyncActions, on completion of the last task, the resultCallback should be invoked with the results in an array. | |
function asyncSeries(taskList, callback) { | |
var arr = []; | |
let tasksCompleted = 0; | |
taskList.reduce((accum, current) => { | |
return accum.then(someVal => { | |
return new Promise((resolve, reject) => { | |
current((value) => { | |
arr.push(value) | |
tasksCompleted++ | |
if (tasksCompleted === taskList.length) { | |
callback.call(null, arr) | |
} else { | |
resolve(value) | |
} | |
}) | |
}) | |
}) | |
}, Promise.resolve()) | |
} | |
const taskList = [ | |
createAsyncTask(), | |
createAsyncTask(), | |
createAsyncTask(), | |
createAsyncTask(), | |
createAsyncTask(), | |
] | |
asyncSeries(taskList, (result) => { | |
console.log("got the results", result) | |
}) | |
// Memoize | |
function memoize(fn) { | |
const cache = {} | |
return function() { | |
const args = JSON.stringify(arguments); | |
if (cache[args]) { | |
return cache[args] | |
} | |
const evaluatedValue = fn.apply(this, arguments); | |
cache[args] = evaluatedValue; | |
return evaluatedValue; | |
} | |
} | |
function factorial(n) { | |
if(n === 0 || n === 1) { | |
return 1 | |
} | |
return factorial(n-1) * n; | |
} | |
const memoizedFactorial = memoize(factorial) | |
memoizedFactorial(1000) // slow | |
memoizedFactorial(1000) // faster | |
//Implement Promise.all | |
function task(time) { | |
return new Promise(function (resolve, reject) { | |
setTimeout(function () { | |
resolve(time); | |
}, time); | |
}); | |
} | |
const taskList = [task(1000), task(5000), task(3000)]; | |
// returns promise with results in an array | |
function myPromiseAll(taskList) { | |
const results = [] | |
let promisesCompleted = 0; | |
return new Promise((resolve, reject) => { | |
taskList.forEach((promise, index) => { | |
promise.then((val) => { | |
results[index] = val; | |
promisesCompleted += 1; | |
if (promisesCompleted === taskList.length) { | |
resolve(results) | |
} | |
}) | |
.catch(error => { | |
reject(error) | |
}) | |
}) | |
}); | |
} | |
myPromiseAll(taskList) | |
.then(results => { | |
console.log("got results", results) | |
}) | |
.catch(console.error) | |
//Promise.allSettled polyfill | |
function promiseAllSettled(promiseArray) { | |
let fullfilledPromisesCount = 0 | |
let result = [] | |
return new Promise((resolve, reject) => { | |
promiseArray.forEach((promiseItem, index) => { | |
console.log('promiseItem before', promiseItem.isFullfilled) | |
promiseItem.then((response) => { | |
console.log('promiseItem after', promiseItem) | |
result[index] = {status: 'resolved', value: response} | |
console.log() | |
fullfilledPromisesCount += 1; | |
if(fullfilledPromisesCount === promiseArray.length) { | |
resolve(result) | |
} | |
}, (error) => { | |
fullfilledPromisesCount += 1; | |
result[index] = {status: 'rejected', error: error} | |
if(fullfilledPromisesCount === promiseArray.length) { | |
resolve(result) | |
} | |
}) | |
}) | |
}) | |
} | |
const taskList = [task(1000), task(2000), task(1)] | |
console.log(promiseAllSettled(taskList).then((allTasks) => { | |
console.log('allTasks', allTasks) | |
}).catch((error) => { | |
console.log('dkdlkl', error) | |
})) | |
//Flatten the array | |
Array.prototype.flatten = function () { | |
let flatArray = [] | |
for (let index = 0; index < this.length; index++) { | |
const element = this[index]; | |
if (Array.isArray(element)) { | |
flatArray = flatArray.concat(this.flatten.call(element)) | |
} else { | |
flatArray.push(element) | |
} | |
} | |
return flatArray; | |
} | |
// function flatten | |
//const nestedArr = [[1], [[1, 4, [5, 3]], [1, 2, 3, 4]]] => [1, 1, 4, 5, 3, 1, 2, 3, 4] | |
const nestedArr = [[1], [[1, 4, [5, 3]], [1, 2, 3, [3, 4, [2, [22, [3, 4, 5, 6, 5, [2]]]]], 4]]] | |
//const nestedArr = [1, 2, 3, 4, [1]] | |
const flat = nestedArr.flatten(); | |
console.log(flat); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment