Closures (or arrow functions, aka lambdas) don't cause memory leaks

Can someone to confirm or infirm if the local variables (here el) can't be cleared by the garbage collector? Or, are modern browsers capable to detect they are unused in the closure?

Yes, modern JavaScript engines are able to detect variables from parent scopes that are visible from a closure but unused. I found a way to prove that.

Step 1: the closure uses a variable of 10 MB

I used this code in Chromium:

class Abc {
    constructor() {
        let arr = new Uint8Array(1024*1024*10) // 10 MB
        let el = document.getElementById("my-btn")
        if (el)
            el.addEventListener("click", ev => this.onClick(ev, arr))
    }
    onClick(ev) {
        console.log("Clicked!", ev.target)
    }
}

new Abc()

Notice the variable arr of type Uint8Array. It is a typed array with a size of 10 megabytes. In this first version, the variable arr is used in the closure.

Then, in the developer tools of Chromium, tab "Profiles", I take a Heap Snapshot:

After ordering by decreasing size, the first row is: "system / JSArrayBufferData" with a size of 10 MB. It is our variable arr.

Step 2: the variable of 10 MB is visible but unused in the closure

Now I just remove the arr parameter in this line of code:

            el.addEventListener("click", ev => this.onClick(ev))

Then, a second snapshot:

The first row has vanished.

This experience confirms that the garbage collector is capable to clean variables from parent scopes that are visible but unused in active closures.

About Function.prototype.bind

I quote the Google JavaScript Style Guide, section on arrow functions:

Never call f.bind(this) or goog.bind(f, this) (and avoid writing const self = this). All of these can be expressed more clearly and less error-prone with an arrow function. This is particularly useful for callbacks, which sometimes pass unexpected additional arguments.

Google clearly recommends to use lambdas rather than Function.prototype.bind.

Related:

  • Why is bind slower than a closure?
  • A benchmark
  • Arrow functions vs. bind() from Dr. Axel Rauschmayer

Answer from Paleo on Stack Overflow
Top answer
1 of 1
34

Closures (or arrow functions, aka lambdas) don't cause memory leaks

Can someone to confirm or infirm if the local variables (here el) can't be cleared by the garbage collector? Or, are modern browsers capable to detect they are unused in the closure?

Yes, modern JavaScript engines are able to detect variables from parent scopes that are visible from a closure but unused. I found a way to prove that.

Step 1: the closure uses a variable of 10 MB

I used this code in Chromium:

class Abc {
    constructor() {
        let arr = new Uint8Array(1024*1024*10) // 10 MB
        let el = document.getElementById("my-btn")
        if (el)
            el.addEventListener("click", ev => this.onClick(ev, arr))
    }
    onClick(ev) {
        console.log("Clicked!", ev.target)
    }
}

new Abc()

Notice the variable arr of type Uint8Array. It is a typed array with a size of 10 megabytes. In this first version, the variable arr is used in the closure.

Then, in the developer tools of Chromium, tab "Profiles", I take a Heap Snapshot:

After ordering by decreasing size, the first row is: "system / JSArrayBufferData" with a size of 10 MB. It is our variable arr.

Step 2: the variable of 10 MB is visible but unused in the closure

Now I just remove the arr parameter in this line of code:

            el.addEventListener("click", ev => this.onClick(ev))

Then, a second snapshot:

The first row has vanished.

This experience confirms that the garbage collector is capable to clean variables from parent scopes that are visible but unused in active closures.

About Function.prototype.bind

I quote the Google JavaScript Style Guide, section on arrow functions:

Never call f.bind(this) or goog.bind(f, this) (and avoid writing const self = this). All of these can be expressed more clearly and less error-prone with an arrow function. This is particularly useful for callbacks, which sometimes pass unexpected additional arguments.

Google clearly recommends to use lambdas rather than Function.prototype.bind.

Related:

  • Why is bind slower than a closure?
  • A benchmark
  • Arrow functions vs. bind() from Dr. Axel Rauschmayer

Discussions

design patterns - Why does JavaScript code usually use lambdas instead of named functions? - Stack Overflow
I'm getting started with JavaScript after a lot of experience with Python and some with C. I've noticed in a few tutorials that there seems to be a strong preference among JavaScript programmers to... More on stackoverflow.com
🌐 stackoverflow.com
functional programming - What is the difference between a function and a lambda? - Software Engineering Stack Exchange
I'm a little bit confused about 'function' and 'lambda'. I've seen some examples showing that the scheme keyword lambda works very similarly to the JavaScript keyword function, but I really don't ... More on softwareengineering.stackexchange.com
🌐 softwareengineering.stackexchange.com
January 18, 2012
javascript - Does use of anonymous functions affect performance? - Stack Overflow
I've been wondering, is there a performance difference between using named functions and anonymous functions in Javascript? for (var i = 0; i More on stackoverflow.com
🌐 stackoverflow.com
Why is a Python Lambda wildly slower than a Javascript Lambda with the same functionality? - Stack Overflow
I am creating a sorting comparison workbench using AWS to host sorting lambdas. I have a bubble sort algorithm implemented in python (python3.8) and javascript (nodejs12.x) lambdas. Both have 512MB More on stackoverflow.com
🌐 stackoverflow.com
People also ask

Why does JavaScript use so many lambda functions?
JavaScript uses many arrow functions because they simplify code, handle this binding better, and fit well with functional programming styles.
🌐
hevodata.com
hevodata.com › home › learn › data strategy
JavaScript Lambda Functions Simplified 101 | Hevo
Why use the lambda function?
Lambda (arrow) functions are used for conciseness, lexical this binding, and aligning with functional programming practices.
🌐
hevodata.com
hevodata.com › home › learn › data strategy
JavaScript Lambda Functions Simplified 101 | Hevo
What does the => mean in JavaScript?
The => symbol in JavaScript is used to define arrow functions. Arrow functions provide a concise syntax for writing functions and have some key differences compared to traditional function expressions.
🌐
hevodata.com
hevodata.com › home › learn › data strategy
JavaScript Lambda Functions Simplified 101 | Hevo
Top answer
1 of 2
6

Wikipedia says "In computer programming, an anonymous function (function literal, lambda abstraction, lambda function, lambda expression or block) is a function definition that is not bound to an identifier."

This makes things relatively easy. For your purposes, "lambda function" and "anonymous function" are effectively synonymous. Therefore, everything you express via the => syntax is a lambda function/anonymous function, and everything you define with the function syntax isn't.

A callback is simply code that is passed to other code to be called at some later time. As you've seen, you can use both named and unnamed functions as callbacks.

The important thing to remember is that "callback" is a role that a function takes on in a specific context. It's entirely possible to call a function as a normal function and also use it as a callback elsewhere.

2 of 2
3

Callback

A Callback function is any function passed as a parameter to another function to be executed when some condition occurs. In your example, when the Promise returned by fetch is fulfilled.

A callback may be anonymous or named, or defined using function or () => {}.

That is, I would define a callback as 'a function that is called else where in your application'. By that definition, the lambda functions passed into an Array.prototype method are callback functions.

Yup! The first parameter to Array.prototype.forEach is even named callbackFn.

Anonymous vs lambda

In software engineering in general, a lambda function and an anonymous function are the same thing. Here is the definition of anonymous function from the C2 wiki.

In a programming language, an unnamed function object (also: "function literal").

Example (in PseudoCode): "lambda(x,y){ x>y }" is an anonymous function object representing the function that tells whether its first argument is greater than its second argument.

A lambda function is understood to be the same thing because of lambda calculus, which involves anonymous functions, and because the lambda keyword is often used in specific language constructs implementing support for anonymous functions.

When we drill down a bit into Javascript specifically, there are two language constructs that implement anonymous functions.

The first one is an anonymous function expression

function() { console.log("Doing stuff") }

The second is an arrow function expression

() => console.log("Doing stuff")

While these provide language support for making anonymous functions, you can still assign names to the result.

const myFunction = function() { console.log("Doing stuff") }

In other languages, such as Java and C#, lambda function refers to a syntax similar to arrow functions. While Javascript doesn't really have a language construct with that name, arrow functions would probably spring to mind for many people because of the similarity.

In conclusion, anonymous functions and lambda functions can be said to be the same thing from a software engineering perspective, but they can also refer to specific language constructs which are not equivalent.

The code below

function printCurrentValue(value) {
    console.log("the value is: " + value)
}

Is then not an anonymous function, nor a lambda function. But if it had been

const printCurrentValue = function(value) {
    console.log("the value is: " + value)
}

Then it's still not an anonymous function, but you could say it's defined using an anonymous function expression.

As for

fetch('/user')
.then((res) => res.json())
.then((json) => console.log(json)); 

(res) => res.json() is

  • Anonymous
  • A callback
  • An arrow function

And you could say it's a lambda function, both referring to it being anonymous and referring to it being an arrow function.

🌐
The Burning Monk
theburningmonk.com › home › first impressions of the fastest javascript runtime for lambda
First impressions of the fastest JavaScript runtime for Lambda | theburningmonk.com
April 22, 2024 - As a result, LLRT is likely less performant than the Node.js runtime for CPU-intensive tasks. However, most Lambda functions do not perform CPU-intensive tasks.
🌐
Admios
admios.com › blog › writing-good-javascript-lets-not-forget-about-performance
Writing good Javascript: Let's not forget about performance
Arrow functions work perfectly ... write a lambda for it, an arrow function is the perfect fit. If you have to pass the scope as an argument to the function, then you should not use an arrow function. So what do arrow functions have to do with performance?...
Find elsewhere
🌐
Medium
medium.com › @chineketobenna › lambda-expressions-vs-anonymous-functions-in-javascript-3aa760c958ae
Lambda Functions Vs Anonymous Functions in JavaScript. | by Chineke Tobenna | Medium
July 27, 2021 - On the other hand, lambda expressions are abstractions which enable a function to be passed around like data. In JavaScript, everything can be treated as an object, this means that a function can be sent into another function as a parameter ...
🌐
Hevo
hevodata.com › home › learn › data strategy
JavaScript Lambda Functions Simplified 101 | Hevo
December 27, 2023 - It frequently occurs after other stored lambda functions have been executed, resulting in a sort of concurrent execution of many jobs. A lambda expression that is run asynchronously is commonly referred to as a “callback.” · Asynchronous callbacks are so common in Javascript that I can’t even begin to list any examples.
🌐
Rost Glukhov
glukhov.org › home › posts › aws lambda performance: javascript vs python vs golang
AWS lambda performance: JavaScript vs Python vs Golang - Rost Glukhov | Personal site and technical blog
We can write lambda function for deployment to AWS in several languages. Let’s compare the performance of (almost empty) functions written in JavaScript, Python and Golang…
🌐
Jasonbutz
jasonbutz.info › 2025 › 05 › javascript-lambda-runtime-benchmarking
JavaScript Lambda Runtime Benchmarking | jasonbutz.info
May 22, 2025 - Last month, I tried out using Bun as a custom JavaScript Lambda runtime and was surprised by the performance difference between Bun and AWS's managed Node.js runtime. The Node runtime had a shorter cold start time, and the invocations had a shorter duration.
🌐
Commerce Architects
commerce-architects.com › post › comparing-lambda-runtime-performance
Comparing Lambda Runtime Performance
April 6, 2025 - Both for application performance and because Lambda invocations are billed by time. The less performant, the longer the code runs and the more it will cost. These costs scale with the number of invocations.
Top answer
1 of 12
100

The performance problem here is the cost of creating a new function object at each iteration of the loop and not the fact that you use an anonymous function:

for (var i = 0; i < 1000; ++i) {    
    myObjects[i].onMyEvent = function() {
        // do something    
    };
}

You are creating a thousand distinct function objects even though they have the same body of code and no binding to the lexical scope (closure). The following seems faster, on the other hand, because it simply assigns the same function reference to the array elements throughout the loop:

function myEventHandler() {
    // do something
}

for (var i = 0; i < 1000; ++i) {
    myObjects[i].onMyEvent = myEventHandler;
}

If you were to create the anonymous function before entering the loop, then only assign references to it to the array elements while inside the loop, you will find that there is no performance or semantic difference whatsoever when compared to the named function version:

var handler = function() {
    // do something    
};
for (var i = 0; i < 1000; ++i) {    
    myObjects[i].onMyEvent = handler;
}

In short, there is no observable performance cost to using anonymous over named functions.

As an aside, it may appear from above that there is no difference between:

function myEventHandler() { /* ... */ }

and:

var myEventHandler = function() { /* ... */ }

The former is a function declaration whereas the latter is a variable assignment to an anonymous function. Although they may appear to have the same effect, JavaScript does treat them slightly differently. To understand the difference, I recommend reading, “JavaScript function declaration ambiguity”.

The actual execution time for any approach is largely going to be dictated by the browser's implementation of the compiler and runtime. For a complete comparison of modern browser performance, visit the JS Perf site

2 of 12
23

Here's my test code:

var dummyVar;
function test1() {
    for (var i = 0; i < 1000000; ++i) {
        dummyVar = myFunc;
    }
}

function test2() {
    for (var i = 0; i < 1000000; ++i) {
        dummyVar = function() {
            var x = 0;
            x++;
        };
    }
}

function myFunc() {
    var x = 0;
    x++;
}

document.onclick = function() {
    var start = new Date();
    test1();
    var mid = new Date();
    test2();
    var end = new Date();
    alert ("Test 1: " + (mid - start) + "\n Test 2: " + (end - mid));
}

The results:
Test 1: 142ms Test 2: 1983ms

It appears that the JS engine doesn't recognise that it's the same function in Test2 and compiles it each time.

🌐
GeeksforGeeks
geeksforgeeks.org › lambda-expressions-in-javascript
Lambda Expressions in JavaScript | GeeksforGeeks
November 19, 2024 - We do not have write a function and think of a name, we can simply provide a lambda expression. Automatically bind this to the surrounding context, eliminating common issues when dealing with callbacks ... The function* is an inbuilt keyword in JavaScript which is used to define a generator function inside an expression.
🌐
Quora
quora.com › What-are-the-performance-of-lambda-expressions-Should-I-use-them
What are the performance of lambda expressions? Should I use them? - Quora
Answer (1 of 6): Concerning about performance is the typical worry of the rookie programmer. Does your program access the disk or the network? If that is the case, all other optimizations are meaningless. The right way to program is: 1. Make the code work. 2. Make the code right. It has to l...
🌐
GeeksforGeeks
geeksforgeeks.org › python › js-equivalent-to-python-lambda
Js equivalent to Python Lambda - GeeksforGeeks
August 5, 2025 - The lambda function eliminates the need for a full function definition. In JavaScript, the closest equivalent to Python’s lambda function is the arrow function. Arrow functions were introduced in ES6 (ECMAScript 2015) and provide a concise syntax for defining anonymous functions.
🌐
Vintasoft
vintasoftware.com › blog › javascript-lambda-and-arrow-functions
JavaScript lambda expressions: a quick guide
May 19, 2025 - The other significant advantage of arrow functions is that it does not have value for this. Inside an arrow function, this is lexically bound to the enclosing scope. Arrow functions eliminate the need for workarounds like saving the this value in a separate variable to access it inside a callback function, resulting in cleaner and more intuitive code.
🌐
Joshdata
joshdata.me › lambda-expressions.html
Lambda Expressions: A Guide
We’ll look at how the same function would be written as a lambda expression. ... In this example, there is a single argument x, the expression x + 1 is computed, and that expression is returned to the caller. It can be written shorter as a lambda expression in modern versions of many languages, including C++ (starting in C++11), C# (starting in C# 9.0), Java (since Java 8), Javascript (starting in ECMAScript 6), and Python (since around Python 2.2):