1. implement curry() with placeholder support
please implement curry() which also supports placeholder.
Here is an example
const join = (a, b, c) => {
return `${a}_${b}_${c}`
}
const curriedJoin = curry(join)
const _ = curry.placeholder
curriedJoin(1, 2, 3) // '1_2_3'
curriedJoin(_, 2)(1, 3) // '1_2_3'
curriedJoin(_, _, _)(1)(_, 3)(2) // '1_2_3'
solutions:

- Let’s first determine the base case
complete
- if arg is equal tocurry.placeholder, wo only need to
args2.shift()
, and don't care aboutargs2.shift()
value, because of recursion - if arg isn't equal to curry.placeholder, return arg
You can see my github file js/medium/curry.js (opens in a new tab)
function curry(fn) {
return function curryInner(...args) {
const complete = args.length >= fn.length && !args.includes(curry.placeholder);
if(complete) return fn(...args);
return (...args2) => {
const res = args.map(arg => arg === curry.placeholder && args2.length ? args2.shift() : arg);
return curryInner(...res, ...args2)
};
}
}
2. implement basic throttle()
Throttling is a common technique used in Web Application, in most cases using lodash solution would be a good choice.
could you implement your own version of basic throttle()?
In case you forgot, throttle(func, delay) will return a throttled function, which will invoke the func at a max frequency no matter how throttled one is called.
Something like below will be used to do the test.
let currentTime = 0
const run = (input) => {
currentTime = 0
const calls = []
const func = (arg) => {
calls.push(`${arg}@${currentTime}`)
}
const throttled = throttle(func, 3)
input.forEach((call) => {
const [arg, time] = call.split('@')
setTimeout(() => throttled(arg), time)
})
return calls
}
expect(run(['A@0', 'B@2', 'C@3'])).toEqual(['A@0', 'C@3'])
solutions:
- If timeout is null, prove that no func is waiting to be executed, so execute func
func.apply(this, args)
- Assign a setTimeout to timeout, if lastArgs is not null, execute func
func.apply(this, lastArgs)
, and reset timeout and lastArgs.
function throttle(func, wait) {
let timeout = null;
let lastArgs = null;
return (...args) => {
if (!timeout) {
func.apply(this, args);
timeout = setTimeout(() => {
lastArgs && func.apply(this, lastArgs)
timeout = null;
lastArgs = null;
}, wait);
} else {
lastArgs = args;
}
}
}