我必须将 Java 8 代码转换为 JavaScript(一种方法,一生一次)。为了加快速度,我希望尽可能实现自动化,然后使用测试套件来解决所有剩余的问题。
我想知道 Java 8 lambda 和 JavaScript(函数)之间有什么区别?
有什么重要的不兼容性吗?
最佳答案
比较 Java lambda 和 JS 函数时需要注意的一件重要事情是两者如何处理作用域。
在 Java 中,lambda 只能有效访问最终变量,并且只能捕获显式需要的变量。在 JS 中,函数可以访问所有父闭包中的所有变量,从而捕获所有内容。
这样做的结果是可能会发生内存泄漏,除非您知道自己在做什么。举个例子:
IntSupplier getSupplier(MyMemoryHeavyClass heavy) {
int x = heavy.hashCode();
return () -> x;
}
此方法将返回一个实际上仅包含 int 的 lambda。这里没有问题。然而,对 JavaScript 的简单翻译...
function getSupplier(heavy) {
var x = heavy.hashCode();
return function() { return x; };
}
乍一看可能不太明显,但这有一个很大的问题。函数表达式将捕获范围内的所有内容,包括 heavy 参数(即使它不是从返回的函数中引用的)。因此,它可以防止 heavy
(在本例中需要大量内存)被垃圾回收,因此只要返回的函数存在,它就会保留在内存中。
编辑
正如评论中所指出的,由于现代引擎似乎更加智能,因此此信息可能有点过时。例如,V8 显然只会捕获它认为必要的内容。但是,它仍然可能被欺骗,因为在同一范围内创建的所有函数似乎共享相同的闭包。
例如,添加行 (function y() { return Heavy; });
,否则几乎不会执行任何操作,将强制 heavy
进入相同的状态return x;
函数使用闭包,造成泄漏。
虽然这个具体示例有些牵强,但当天真地翻译包含多个 lambda 的 Java 方法时,可能会出现类似的问题,这绝非不可想象。
关于javascript - Java 8 Lambda 构造和 JavaScript 之间的确切区别是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59057560/