On-site Interview Questions
3 min readNov 10, 2023
1. Removing Duplicate Strings
// const exampleStr = 'Hello world world'
// const output = 'Hello world'
function removeDuplicates(str) {
return [...new Set(str.split(' '))].join(' ')
}
2. Flattening an Array
// Without using .flat()
// const exampleArr = [1,2,[3,4,[5,6,7],8],9,10]
// const output = [1,2,3,4,5,6,7,8,9,10]
function flatten(arr) {
return arr.reduce((acc, item) => {
if (Array.isArray(item)) {
return acc.concat(flatten(item))
} else {
return acc.concat(current)
}
}, [])
}
3. JavaScript Scope .bind()
// Implement Function.prototype.bind()
/* usage:
const foo = function() {
console.log(this.bar)
}
let baz = foo.bind({bar: 'hello'})
baz() // >>> Hello
*/
// only context
Function.prototype.bind = function(context) {
const originalFn = this
return function() {
originalFn.call(context)
}
}
// solution with arguments
Function.prototype.myBind = function (context, ...args) {
const originalFn = this
return function (...boundArgs) {
const allArgs = args.concat(boundArgs)
return originalFn.apply(context, allArgs)
};
};
4. Timing — Debounce
In JavaScript, a debounce function is used to limit the rate at which a function is invoked. It is often employed in scenarios where a function is triggered by an event that may fire multiple times, and you want to ensure that the function is executed only after a certain period of inactivity.
// debounce
function debounce(func, delay) {
let timeoutId
return function(...args) {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => {
func.apply(this, args)
timeoutId = undefined
}, delay)
}
}
// example usage
function handleInput(value) {
console.log(`Input value: ${value}`);
}
const debouncedInputHandler = debounce(handleInput, 500);
// simulating input events
debouncedInputHandler('A');
debouncedInputHandler('B');
debouncedInputHandler('C');
// after 500 milliseconds of inactivity, the handleInput function will be called with the latest input value.
5. Trees
// Given two identical DOM trees, A and B. For DOM three A, we have
// the location of an element. Create a function to find that element
// in tree B.
function findCorrespondingElement(nodeA, locationA, treeB) {
const pathToElementInB = locationToPath(nodeA, locationA)
let currentElementB = treeB
for (const step of pathToElementInB) {
currentElementB = currentElementB && currentElementB.children[step]
if (!currentElementB) {
return null // Element not found in tree B
}
}
return currentElementB
}
function locationToPath(root, location) {
const path = [];
let pointer = location;
while (pointer !== root) {
const parent = pointer.parentNode
const index = Array.from(parent.children).indexOf(pointer)
path.unshift(index)
pointer = parent
}
return path
}
6. Rendering
The best approach is to use the translate
, transform
CSS property. In JS we use requestAnimationFrame()
// Create a function to move an element. The function arguments are,
// distance, duration, and the element move.
function moveElement(duration, distance, element) {
const start = performance.now()
function move(currentTime) {
const elapsed = currentTime - start
const progress = elapsed / duration
const amountToMove = progress * distance
element.style.transform = `translateX(${ amountToMove }px)`
if (amountToMove < distance) {
requestAnimationFrame(move)
}
}
requestAnimationFrame(move)
}
7. Promises
// Create a sleep function that takes one parameter (time) and
// will wait 'time' ms
/*
async function run() {
await sleep(500)
console.log('hello')
await sleep(500)
console.log('world')
}
*/
function sleep(time) {
return new Promise((resolve) => {
setTimeout(resolve, time)
})
}
// Create a function to turn any function into a 'promisified' function.
// Any function to be promisified will always have a callback as the last array
// The callback will always have this signature:
// function (result) {}
/*
const exampleFn = function (x, y, callback) {}
const promisedFn = promisify(exampleFn)
promisedFn().then(...).then(...)
*/
function promisify(fn) {
return function(...args) {
return new Promise((resolve, reject) => {
function cb(result) {
resolve(result)
}
fn.apply(this, args.concat(cb))
})
}
}