Last active
May 24, 2019 03:21
-
-
Save zainxyz/8dba7549ee35e3e5a52f54841cec920b to your computer and use it in GitHub Desktop.
Couple of good JavaScript Interview Questions (solved using ES6+)
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
/** | |
* What is the difference between '==' and '===' in JavaScript? | |
* | |
* '==' matches just the value, where as '===' (also known as the 'strict') operator matches both | |
* the value and the type. | |
*/ | |
console.log(100 == '100'); // true, because only value matter | |
console.log(100 === '100'); // false, because type and value both matter | |
/** | |
* What is the difference between 'null' and 'undefined' in JavaScript? | |
* | |
* 'null' is an assignment value, which can be assigned to a JavaScript variable, representing that | |
* the variable has no value; where as 'undefined' represents that a variable has been declared or | |
* called but there is no value associated with it. | |
*/ | |
/** | |
* Describe the functionality of the 'use strict' keyword. | |
* | |
* 'use strict' keyword defines the usage of the JavaScript's 'strict mode', where the usage of | |
* undeclared variables is not allowed, common coding errors and exceptions are caught during the | |
* development cycle, throws errors where global objects are accessed, plus many more common | |
* JavaScript errors / bloopers. | |
*/ | |
/** | |
* Explain hoisting in JavaScript. | |
* | |
* Hoisting is a concept in JaaScript where all of the declarations are moved to the top of the | |
* current scope. Meaning a variable or function can be used before it has been declared. | |
* NOTE: JavaScript only hoists declarations and not initializations. | |
*/ | |
/** | |
* Explain 'event bubbling' in JavaScript. | |
* | |
* Event bubbling is a concept in JavaScript where an event triggered at the deepest child element | |
* can trigger an event on its parent elements in nesting order. | |
* | |
* i.e. In the React JS world, when a user clicks on the <ClickMeButton /> the event named | |
* 'clickedOnChild' in the parent component, <ParentComponent />, is triggered. | |
*/ | |
class ParentComponent extends Component { | |
constructor(props) { | |
super(props); | |
this.clickedOnChild = this.clickedOnChild.bind(this); | |
} | |
clickedOnChild(e) { | |
console.log('You have clicked on the child element'); | |
} | |
render() { | |
return <TheButtons clickedOnChild={this.clickedOnChild} />; | |
} | |
} | |
const TheButtons = ({ clickedOnChild }) => <ClickMeButton onClick={clickedOnChild} />; | |
/** | |
* How does one prevent 'event bubbling'? | |
* | |
* One can prevent event bubbling by using 'event.stopPropagation()' | |
*/ | |
/** | |
* What is Object Oriented Programming (OOP)? | |
* | |
* Object-oriented programming (OOP) is a programming language organized around 'objects' rather | |
* than 'actions', data rather than logic. | |
*/ | |
/** | |
* Balanced Parenthesis | |
* | |
* Write a function to check whether or not the given string is balanced or not. | |
* Complete the balancedParenthesis function in the editor below. It has 1 parameter: | |
* 1. A string, theString, denoting a set of parenthesis. | |
* The function must return a Boolean value, true or false, denoting the passed in string has a | |
* balanced set of parenthesis. | |
* | |
* Sample Input: balancedParenthesis('((()))') | |
* Sample Output: true | |
* | |
* Sample Input: balancedParenthesis('((()') | |
* Sample Output: false | |
* | |
* Sample Input: balancedParenthesis(')))(((') | |
* Sample Output: false (since we cannot begin with a closed parenthesis) | |
* | |
* @method balancedParenthesis | |
* @param {String} theString The string containing the parenthesis | |
* @return {Boolean} Whether or not the string has a set of balanced parenthesis | |
*/ | |
const balancedParenthesis = theString => | |
!theString.split('').reduce((accum, char) => { | |
// This is for cases where the parenthesis is balanced but in not the correct order. | |
// i.e. ')(' or ')))(((' | |
if (accum < 0) { | |
return accum; | |
} | |
// For each opening parenthesis add to the accumulator | |
if (char === '(') { | |
return ++accum; | |
} | |
// For each closing parenthesis remove from the accumulator | |
if (char === ')') { | |
return --accum; | |
} | |
// Otherwise just return the accumulator | |
return accum; | |
}, 0); | |
/** | |
* Remove Duplicates! | |
* | |
* Given a list of numbers, theList, remove all of the duplicate values from the list. | |
* Complete the removeDuplicates function in the editor below. It has 1 parameter: | |
* 1. An array, theList, denoting the list of numbers. | |
* The function must return an array of numbers, without any duplicate values. | |
* | |
* Sample Input: removeDuplicates([1, 1, 2, 3, 4, 4]) | |
* Sample Output: [1, 2, 3, 4] | |
* | |
* Sample Input: removeDuplicates([1, 2, 2, 2, 2, 2, 2, 2, 3]) | |
* Sample Output: [1, 2, 3] | |
* | |
* @method removeDuplicates | |
* @param {Array} theList A list of values | |
* @return {Array} The filtered list without any duplicate values. | |
*/ | |
const removeDuplicates = theList => theList.filter((item, idx) => theList.indexOf(item) === idx); | |
// Alternate + better solution | |
const removeDuplicates = theList => Array.from(new Set(theList)); | |
/** | |
* Flatten the Array! | |
* | |
* Given an array, theList, which can contain nested array of values, flatten it out. | |
* Complete the flattenArray function in the editor below. It has 1 parameter: | |
* 1. An array, theList, denoting the array of nested array values. | |
* The function must return a flattened out array. | |
* | |
* Sample Input: flattenArray(['a', ['b', ['c', 'd'], ['e', 'f']]]) | |
* Sample Output: ['a', 'b', 'c', 'd', 'e', 'f'] | |
* | |
* @method flattenArray | |
* @param {Array} list A list of values which can have nested arrays | |
* @return {Array} The final flattened array | |
*/ | |
function flatten(list) { | |
return list.reduce( | |
(final, current) => | |
Array.isArray(current) | |
? final.concat(flatten(current)) | |
: final.concat(current), | |
[] | |
); | |
} | |
/** | |
* Find the number! | |
* | |
* Given an unsorted array of n elements, find if the element k is present in the array or not. | |
* Complete the findNumber function in the editor below. It has 2 parameters: | |
* 1. An array of integers, arr, denoting the elements in the array. | |
* 2. An integer, k, denoting the element to be searched in the array. | |
* The function must return a string 'YES' or 'NO' denoting if the element is present in the array | |
* or not. | |
* | |
* Sample Input: findNumber([4, 6, 2, 4, 6, 2, 3, 5, 1], 2) | |
* Sample Output: 'YES' | |
* | |
* Sample Input: findNumber([1, 2, 3, 4, 5, 5, 2, 4, 1, 9], 6) | |
* Sample Output: 'NO' | |
* | |
* @method findNumber | |
* @param {Array} arr The list of numbers | |
* @param {Number} k The number to find | |
* @return {String} Whether or not the number is present in the given list | |
*/ | |
const findNumber = (arr, k) => (arr.find(item => item === k) ? 'YES' : 'NO'); | |
/** | |
* Odd Numbers! | |
* | |
* Given two integers, l and r, print all the odd numbers between l and r (l and r inclusive) | |
* Complete the oddNumbers function in the editor below. It has 2 parameters: | |
* 1. An integer, l, denoting the left part of the range. | |
* 2. An integer, r, denoting the right part of the range. | |
* The function must return an array of integers denoting the odd numbers between l and r. | |
* | |
* Sample Input: oddNumbers(2, 5) | |
* Sample Output: [3, 5] | |
* | |
* Sample Input: oddNumbers(3, 9) | |
* Sample Output: [3, 5, 7, 9] | |
* | |
* @method oddNumbers | |
* @param {Number} leftRange The left range of the list | |
* @param {Number} rightRange The right range of the list | |
* @return {Array} The list of odd numbers | |
*/ | |
const oddNumbers = (leftRange, rightRange) => { | |
const oddList = []; | |
for (let i = leftRange; i <= rightRange; i += 1) { | |
if (i % 2 !== 0) { | |
oddList.push(i); | |
} | |
} | |
return oddList; | |
}; | |
/** | |
* Even Numbers! | |
* | |
* Given two integers, l and r, print all the even numbers between l and r (l and r inclusive) | |
* Complete the evenNumbers function in the editor below. It has 2 parameters: | |
* 1. An integer, l, denoting the left part of the range. | |
* 2. An integer, r, denoting the right part of the range. | |
* The function must return an array of integers denoting the even numbers between l and r. | |
* | |
* Sample Input: evenNumbers(2, 6) | |
* Sample Output: [2, 4, 6] | |
* | |
* Sample Input: evenNumbers(1, 12) | |
* Sample Output: [2, 4, 6, 8, 10, 12] | |
* | |
* @method evenNumbers | |
* @param {Number} leftRange The left range of the list | |
* @param {Number} rightRange The right range of the list | |
* @return {Array} The list of even numbers | |
*/ | |
const evenNumbers = (leftRange, rightRange) => { | |
const evenList = []; | |
for (let i = leftRange; i <= rightRange; i += 1) { | |
if (i % 2 === 0) { | |
evenList.push(i); | |
} | |
} | |
return evenList; | |
}; | |
/** | |
* Product of All (but me) | |
* | |
* Given a list of integers, theList, return a new list such that outputList[i] is equal to the | |
* product of all the elements in the original list, other than itself. | |
* Complete the productOfAllButMe function in the editor below. It has 1 parameter: | |
* 1. An array, theList, denoting a list of integers. | |
* The function must return a new array, outputList, such that outputList[i] is equal to the product | |
* of all of the elements in the original list, other than the originalList[i] itself. | |
* | |
* Sample Input: productOfAllButMe([1, 2, 3, 4, 1]) | |
* Sample Output: [24, 12, 8, 6, 24] | |
* | |
* Sample Input: productOfAllButMe([-2, 5, 9, 100]) | |
* Sample Output: [4500, -1800, -1000, -90] | |
* | |
* @method productOfAllButMe | |
* @param {Array} theList The list of integers | |
* @return {Array} A list of integers containing the product of all but theList[i] | |
*/ | |
const productOfAllButMe = theList => | |
theList.map((item, itemIdx) => { | |
let productOfAll = 1; | |
theList.forEach( | |
(otherItem, otherItemIdx) => | |
otherItemIdx !== itemIdx ? (productOfAll *= otherItem) : productOfAll | |
); | |
return productOfAll; | |
}); | |
/** | |
* Array Intersection | |
* | |
* Given two arrays, firstList and secondList, find their intersection. | |
* Complete the arrayIntersection function in the editor below. It has 2 parameters: | |
* 1. An array, firstList, denoting a list of items. | |
* 2. An array, secondList, denoting a list of items. | |
* The function must return a new and unique set of items containing the intersection of the passed | |
* in arrays. | |
* | |
* Sample Input: arrayIntersection([2, 2, 4, 1, 3, 0], [1, 2, 0, 2]) | |
* Sample Output: [2, 1, 0] | |
* | |
* Sample Input: arrayIntersection([1, 2, 3, 4, 5, 6, 6, 6, 6, 6, 7], [7, 6, 9, 0, 0, 1]) | |
* Sample Output: [1, 6, 7] | |
* | |
* @method arrayIntersection | |
* @param {Array} firstList The first list | |
* @param {Array} secondList The second list | |
* @return {Array} The array including the intersected items | |
*/ | |
const arrayIntersection = (firstList, secondList) => [ | |
...new Set(firstList.filter(item => secondList.includes(item))), | |
]; | |
/** | |
* Array Difference | |
* | |
* Given two arrays, firstList and secondList, find their difference. | |
* Complete the arrayDifference function in the editor below. It has 2 parameters: | |
* 1. An array, firstList, denoting a list of items. | |
* 2. An array, secondList, denoting a list of items. | |
* The function must return a new and unique set of items containing the difference of the passed | |
* in arrays. | |
* | |
* Sample Input: arrayDifference([2, 2, 4, 1, 3, 0], [1, 2, 0, 2]) | |
* Sample Output: [4, 3] | |
* | |
* Sample Input: arrayDifference([1, 2, 3, 4, 5, 6, 6, 6, 6, 6, 7], [7, 6, 9, 0, 0, 1]) | |
* Sample Output: [2, 3, 4, 5] | |
* | |
* @method arrayDifference | |
* @param {Array} firstList The first list | |
* @param {Array} secondList The second list | |
* @return {Array} The array including the different items | |
*/ | |
const arrayDifference = (firstList, secondList) => [ | |
...new Set(firstList.filter(item => !secondList.includes(item))), | |
]; | |
/** | |
* Are we an Isomorphic String? | |
* | |
* Given two strings, string_1 and string_2, check to see if the two strings are isomorphic. | |
* Isomorphic strings, meaning if all occurrences of a character in the string_1 can be replaced | |
* with another character to get the end result of the string_2. The order of the characters | |
* matters. There should be a one-to-one mapping or every character of string_1 and string_2. | |
* Complete the isomorphicStrings function in the editor below. It has 2 parameters: | |
* 1. A string, string_1, denoting the first string to test. | |
* 2. A string, string_2, denoting the second string to test. | |
* The function must return a Boolean if the two strings are indeed isomorphic strings. | |
* | |
* Sample Input: isomorphicStrings('title', 'paper') | |
* Sample Output: true | |
* | |
* Sample Input: isomorphicStrings('add', 'dog') | |
* Sample Output: false | |
* | |
* Sample Input: isomorphicStrings('abc', 'xyz') | |
* Sample Output: true | |
* | |
* @method isomorphicStrings | |
* @param {String} string_1 The first string | |
* @param {String} string_2 The second string | |
* @return {Boolean} If the two strings are indeed isomorphic | |
*/ | |
const isomorphicStrings = (string_1, string_2) => { | |
// Check to see if the two strings are of the same length. | |
if (string_1.length !== string_2.length) { | |
return false; | |
} | |
// Create an empty map which we'll fill up later | |
const lettersMap = {}; | |
// Split up the first string by character, resulting in an array | |
const string_1_lettersList = string_1.split(''); | |
// Split up the second string by character, resulting in an array | |
const string_2_lettersList = string_2.split(''); | |
// Loop through each of the characters of the first string | |
for (const letter in string_1_lettersList) { | |
const string_1_letter = string_1_lettersList[letter]; | |
const string_2_letter = string_2_lettersList[letter]; | |
// If the current map does not include the first letter of the string_1 then map it to the value | |
// of the string_2_letter (from the second string) | |
if (lettersMap[string_1_letter] === undefined) { | |
lettersMap[string_1_letter] = string_2_letter; | |
} else if (lettersMap[string_1_letter] !== string_2_letter) { | |
// If the current map includes the first letter of the string_1 then we don't need to map it | |
// to the value of the string_2_letter since the string_1_letter has already been mapped to | |
// more then one letter. | |
return false; | |
} | |
} | |
// Finally return true if all of the conditions have been passed. | |
// This means that the two strings are isomorphic. | |
return true; | |
}; | |
/** | |
* Convert Decimal to Binary | |
* | |
* Given a number, decimalDigit, print it's binary representation. | |
* Complete the convertDecimalToBinary function in the editor below. It has 1 parameter: | |
* 1. A number, decimalDigit, denoting the passed in decimal value of a number. | |
* The function must return a string containing the binary representation of the number. | |
* | |
* Sample Input: convertDecimalToBinary(3) | |
* Sample Output: '11' | |
* | |
* Sample Input: convertDecimalToBinary(4) | |
* Sample Output: '100' | |
* | |
* Sample Input: convertDecimalToBinary(156) | |
* Sample Output: '10011100' | |
* | |
* @method convertDecimalToBinary | |
* @param {Number} decimalDigit The decimal digit | |
* @return {String} The binary representation of the passed in decimal | |
*/ | |
const convertDecimalToBinary = decimalDigit => Number.parseInt(decimalDigit, 10).toString(2); | |
// | |
// A complete opposite of this method, to convert binary to decimal would be | |
// | |
const convertBinaryToDecimal = binaryDigit => Number.parseInt(binaryDigit, 2).toString(10); | |
/** | |
* Mr. Fibonacci | |
* | |
* A series of numbers in which each number, | |
* (Fibonacci number) is the sum of the two preceding numbers. | |
* The simplest is the series 1, 1, 2, 3, 5, 8, etc. | |
*/ | |
const fib = n => n < 2 ? n : fib(n - 1) + fib(n - 2); | |
/** | |
* Throttle! | |
* | |
* Develop a 'throttle' function, i.e. a function that should return a new function that would be | |
* called no more than once per specified timeout. | |
* Complete the throttle function in the editor below. It has 2 parameters: | |
* 1. A function that is to be throttled. | |
* 2. A limit in milliseconds. | |
* The function must return a new function which would be called no more than once per specified | |
* timeout. | |
* | |
* Sample Input: | |
* const foo = throttle(() => (console.log('test')), 1000); | |
* foo(); // should console.log | |
* foo(); // should not console.log because 1000ms hasn't passed yet | |
* setTimeout(foo, 1001); // should console.log after 1001ms | |
* | |
* @method throttle | |
* @param {Function} fn The passed in function to be called | |
* @param {Number} limit The number of milliseconds to waiting | |
* @param {Object} [context=this] The passed in context | |
* @return {Function} The returned throttled function | |
*/ | |
const throttle = (fn, limit, context = this) => { | |
let timeout = null; | |
let args = null; | |
const later = () => { | |
fn.apply(context, args); | |
timeout = null; | |
}; | |
return () => { | |
if (!timeout) { | |
args = arguments; | |
timeout = setTimeout(later, limit); | |
} | |
}; | |
}; | |
/** | |
* Let's imagine we have an 'x' number of API endpoints: | |
* | |
* '/1' - that outputs { 'value': 1 } | |
* '/2' - that outputs { 'value': 2 } | |
* '/3' - that outputs { 'value': 3 } | |
* ... | |
* '/1000' - that outputs { 'value': 1000 } | |
* | |
* The goal is to develop a function that, given the array like ['/1', '/2', '/3'], | |
* would make an 'x' number of sequential calls and collects the output. | |
*/ | |
/** | |
* List of URLs | |
* @type {Array} | |
*/ | |
const urls = ['/1', '/2', '/3', '/4', '/5']; | |
/** | |
* Main list of collected data | |
* @type {Array} | |
*/ | |
const collectedData = []; | |
/** | |
* A function to collect the given data | |
* @method collectData | |
* @param {Object} res The API response | |
* @return {Array} Push the result to the collectedData array. | |
*/ | |
const collectData = res => collectedData.push(res.value); | |
/** | |
* A list of fetch() calls based on the passed in urls | |
* @method buildPromiseCalls | |
* @param {Array} urls The passed in list of urls | |
* @return {Array} A list of array's with fetch calls | |
*/ | |
const buildPromiseCalls = urls => urls.map(url => () => fetch(url).then(res => collectData(res))); | |
/** | |
* Serialize the calls, calling them in a sequential order, one after the other | |
* @method serializeCalls | |
* @param {Array} calls A list of fetch() calls | |
* @return {Array} List of serialized calls | |
*/ | |
const serializeCalls = calls => | |
calls.reduce( | |
(promise, fn) => promise.then(res => fn().then(Array.prototype.concat.bind(res))), | |
Promise.resolve([]) | |
); | |
serializeCalls(buildPromiseCalls(urls)) | |
.then(res => console.log(res)) | |
.catch(err => console.log(err)); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment