One important thing to note when comparing Java lambdas and JS functions is how the two treat scoping.
In Java, lambdas can only access effectively final variables and only captures those that are explicitly required. In JS, functions can access all variables in all the parent closures and thus captures everything.
A result of this is the possibility of memory leaks unless you know what you're doing. As an example:
IntSupplier getSupplier(MyMemoryHeavyClass heavy) {
int x = heavy.hashCode();
return () -> x;
}
This method will return a lambda that effectively only contains an int. No problems here. However, a naive translation to JavaScript...
function getSupplier(heavy) {
var x = heavy.hashCode();
return function() { return x; };
}
It may not be obvious at a glance, but this has a major problem. The function expression will capture EVERYTHING within the scope, including the heavy
parameter (even though it's not referenced from within the returned function). As a result, it prevents heavy
(which in this example requires a large amount of memory) from being garbage collected and will thus remain in memory for as long as the returned function exists.
EDIT
As pointed out in the comments, this information may be a bit out of date as modern engines appear to be more intelligent. V8, for instance, will apparently only capture whatever it deems necessary. However, it can still be tricked as all functions created in the same scope appear to share the same closure.
For instance, adding the line (function y() { return heavy; });
, which would otherwise do pretty much nothing, will force heavy
into the same closure as the return x;
function uses, creating the leak.
While far-fetched in this specific example, it's far from unthinkable that similar problems may occur when naively translating Java methods containing multiple lambdas.