The challenge
Write once(fn) that returns a new function. The first time it’s called, it calls fn with the same arguments and returns the result. After that, it never calls fn again, and just returns that first result.
const init = once(() => "started");
init(); // "started"
init(); // "started" (fn didn’t run again)
Try it
Write your answer below, then press Check my answer. Your code runs right here in your browser, and the tests tell you what works.
It prints
What the tests check
- Fn runs only once:
(() => { let calls = 0; const f = once(() => ++calls); f(); f(); f(); return calls; })()gives1 - Later calls return the first result:
(() => { const add = once((a, b) => a + b); add(2, 3); return add(10, 10); })()gives5
Hints
Stuck? Open one hint at a time. Try again after each one.
Hint 1
Use two variables in the closure: let done = false; and let result;.
A solution
There’s always more than one right way. Read it, make sure you understand it, then try writing it yourself without looking.
Show one possible solution
function once(fn) {
let done = false;
let result;
return (...args) => {
if (!done) {
done = true;
result = fn(...args);
}
return result;
};
}
Learn what you need
This exercise uses what Grade 9: Scope, Hoisting & Closures teaches. Read those notes first if any of it is new.