Skip to content

Instantly share code, notes, and snippets.

@zainxyz
Last active May 24, 2019 03:21
Show Gist options
  • Save zainxyz/8dba7549ee35e3e5a52f54841cec920b to your computer and use it in GitHub Desktop.
Save zainxyz/8dba7549ee35e3e5a52f54841cec920b to your computer and use it in GitHub Desktop.
Couple of good JavaScript Interview Questions (solved using ES6+)
/**
* 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