Javascript 是否可以定义一个内联的;“静态”;lambda(箭头)函数?

Javascript 是否可以定义一个内联的;“静态”;lambda(箭头)函数?,javascript,memory,ecmascript-6,lambda,arrow-functions,Javascript,Memory,Ecmascript 6,Lambda,Arrow Functions,我的代码涉及很多事件处理程序,它们不需要任何上下文(范围)来执行。当我使用内联lambda函数而不是静态声明(常量)lambda函数时,每次分配事件处理程序时都会创建一个新的事件处理程序 问题:是否可以定义内联lambda函数,该函数不会在每次将lambda作为回调传递时创建新的函数对象。(假设不需要唯一的上下文范围。) 两个例子说明了符号和内存使用之间的权衡。 1。内联lambda:(所需的符号,不必要的内存消耗) 所需的符号,但为每个divId创建一个新的函数回调(e=>console.lo

我的代码涉及很多事件处理程序,它们不需要任何上下文(范围)来执行。当我使用内联lambda函数而不是静态声明(常量)lambda函数时,每次分配事件处理程序时都会创建一个新的事件处理程序

问题:是否可以定义内联lambda函数,该函数不会在每次将lambda作为回调传递时创建新的
函数
对象。(假设不需要唯一的上下文范围。)

两个例子说明了符号和内存使用之间的权衡。 1。内联lambda:(所需的符号,不必要的内存消耗)

所需的符号,但为每个
divId
创建一个新的
函数
回调(
e=>console.log(e)
),尽管回调不依赖于任何上下文信息(因此每个
divId
在功能上是等效的)。如果有一种方法可以只传递一个指向这个函数的指针,那就太好了

2。静态声明的lambda:(不需要的符号,需要的和最小的内存消耗)

不需要的表示法(需要额外的常量),但在上面,只为所有三个
divid创建一次
函数
回调(
staticLambda
)。 想象一下,这在类方法中会是什么样子;lambda函数需要在其各自的方法之外声明为类的静态属性,因此破坏了lambda的优雅性(它非常擅长将回调代码保留在传递它的位置)


注意:这是一个简化的示例。我意识到创建2个(共3个)不必要的回调不会对性能产生实质性影响,但是,我感兴趣的是正确处理数量级以上的回调。

您可能希望在函数中添加事件侦听器,如下所示:

function addListeners(ids, listener){
  for( const divId of ids){
     document.getElementById(divId).addEventListener("click", listener);
  }
}
addListeners(["div1", "div2", "div3"], e => console.log(e));
现在您可以这样调用函数:

function addListeners(ids, listener){
  for( const divId of ids){
     document.getElementById(divId).addEventListener("click", listener);
  }
}
addListeners(["div1", "div2", "div3"], e => console.log(e));

虽然这些类型的优化确实有助于提高性能(),但我不认为它有很大的影响,也不应该仅仅因为性能原因而进行优化,但是您的案例当然是有效的

如果要管理多个事件侦听器,则还应注意在它们未使用时删除它们。如果仍然有对原始处理程序的引用,并因此在附加处理程序的作用域之外的某个位置声明该处理程序,那么删除事件侦听器是最简单的


我还认为,将“简单”事件处理程序放在它们自己的函数中,并将它们保存在单独的模块或文件中是一种很好的做法,这样可以更容易地进行重构。这也解决了性能问题。

内存使用不应成为您选择一种表单而不是另一种表单的原因。原因有二:

  • 使用量很小,在大多数情况下几乎无法测量

  • Javascript解释器很可能在优化字节码或JIT机器码时编译单个函数

  • 但是,由于其属性,您应选择其中一种形式:

  • 当有多个位置使用同一逻辑时,声明隐式函数。始终寻找重构代码的机会,尤其是在命名函数时进行简单的重构。它减少了将来修复bug时的工作量

  • 当每次调用函数时都需要实例化一个新闭包时,请使用IIFE(内联)。现代javascript可能会将其编译为单个函数,但每次“重新声明”该函数时,它们都会创建一个新的闭包


  • 我看不出有什么办法。我想到的唯一一件事是把它留给一个能够确定函数不使用任何循环变量的预处理器,并重写代码以在更高的范围内提升声明。@FelixKling我使用的是typescript(预处理器),这会带来更多的可能性吗?我甚至不需要自动检查上下文变量的使用情况,如果我可以使用(或定义)一个自定义箭头语法来强制执行此行为,就可以做到这一点。感谢您的关注。本质上,这与我的第二个示例(2.静态声明的lambda)相同,其中
    由一个函数包装。这对我不起作用的原因是,我一时不知道我所有的
    divid
    将是什么(我同意我的代码中不清楚这一点)。(例如,假设lambda是在HTML元素的构造函数中传递的eventhandler。我更希望在构造函数中编写lambda,而不是将其声明为静态属性,然后在构造函数中使用它。)Hi@Simon。我认为您希望动态地构建lambda。这不能这样做。但是,您可以做的是从另一个函数返回一个lamdba/函数。这样,想要的行为(返回的函数)可以在运行时依赖于其他值(例如函数的参数或对象的状态)。我将只创建一次lambda作为静态常量,然后重用它(我不需要运行时信息,比如范围绑定/对象状态)。谢谢你一直思考!第1.1点:当我创建100.000个HTML对象时,使用率真的很小吗?使用这100.000个完全相同的事件处理程序?第1.2点:我怀疑这是按照你说的方式编写的。我用firebug profiler观察了它,发现为每个lambda创建了一个
    函数
    对象。第1.3点:用法本身可能无法测量,但我感觉垃圾收集器在这些对象上花费了很多时间。第2.1点:这与函数的命名无关,毕竟,我只在一个位置编写它。第2.2点:我来看看这个能做什么!我会让你知道的!到目前为止,在野外(如,真实世界的经验)