Fundamentals 11 min read

Lazy Evaluation, Thunks, and Generators in JavaScript Functional Programming

This article explores how closures, currying, pure functions, thunks, and ES6 generators enable lazy evaluation in JavaScript, illustrating the concepts with code examples and showing how they can reduce unnecessary computation, control execution order, and even create infinite sequences.

Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Lazy Evaluation, Thunks, and Generators in JavaScript Functional Programming

JavaScript, despite being an eager‑evaluation language, can adopt lazy‑evaluation techniques through functional‑programming concepts such as closures, currying, pure functions, and generators. The article begins by explaining that closures inherently delay computation because the inner function captures variables for later use.

Example of a closure that returns a new function:

function addA(A){
    return function(B){
        return B+A
    }
}
let count = addA(7)
console.log(count(8)) // 15

Currying is presented as a twin of closures, turning a multi‑argument function into a chain of single‑argument functions, e.g., add(1,2,3) becomes add(1)(2)(3)() . The following snippet demonstrates a curried addition that only performs the sum when the final call receives no arguments:

function addCurry(){
    let arr = [...arguments]
    let fn = function(){
        if(arguments.length === 0){
            return arr.reduce((a,b) => a + b) // compute when args are empty
        } else {
            arr.push(...arguments)
            return fn
        }
    }
    return fn
}

Pure functions are discussed, and the idea of wrapping impure operations (IO, HTTP, DOM) in a “box” (a thunk) is introduced so that side effects are only realized when the thunk is explicitly evaluated, mirroring the concept of a monad.value() call.

The term “lazy evaluation” (or “惰性求值”) is linked to thunks. A thunk is defined as a parameter‑less closure that carries both the unevaluated expression and its environment, allowing delayed execution.

JavaScript’s native Promise is shown not to be lazy because it starts executing immediately upon creation. In contrast, ES6 generators provide true laziness by yielding control back to the caller until next() is invoked.

function* gen(x){
    const y = yield x + 6;
    return y;
}
const g = gen(1);
g.next() // { value: 7, done: false }
g.next() // { value: undefined, done: true }

Generators can also model asynchronous flows. By yielding a promise or a value, the asynchronous operation only starts when the generator’s next() is called:

function* st1(){
    setTimeout(() => {
        console.log("done promise")
    },1000)
    yield("done promise")
}
let aThunk = st1()
console.log(aThunk) // Generator {}
// Execution begins only after aThunk.next()

Practical patterns such as sequential API requests, infinite sequences, and alternating generators are demonstrated. For example, an infinite ID generator:

function* idMaker(){
    let index = 0;
    while(true) yield index++;
}
let gen = idMaker();
console.log(gen.next().value); // 0
console.log(gen.next().value); // 1

And an alternating infinite sequence generator:

function* alternate(...seq){
    while(true){
        for(let item of seq){
            yield item;
        }
    }
}
let alternator = alternate('one','two','three');
for(let i=0;i<6;i++){
    console.log(`${alternator.next().value}`);
}

The article concludes that generators, together with closures, currying, and composition, embody the same “delayed processing” philosophy, allowing JavaScript developers to write more efficient, controllable, and expressive code.

JavaScriptFunctional Programminglazy-evaluationCurryingClosuresGeneratorsThunks
Rare Earth Juejin Tech Community
Written by

Rare Earth Juejin Tech Community

Juejin, a tech community that helps developers grow.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.