什么是使用匿名函数而不是命名功能在JavaScript事件代码回调和参数的好处是什么?(What a

2019-06-23 21:08发布

我是新十岁上下为JavaScript。 我明白了许多语言的概念,我一直在原型继承模型读书了,我挑起我的口哨随着越来越多的互动前端的东西。 这是一个有趣的语言,但我总是有点关闭由回调意大利面是典型的许多不平凡的互动模式。

东西似乎总是很奇怪,我是,尽管可读性的噩梦是JavaScript的嵌套回调的窝,一两件事,我在很多例子和教程很少看到的是使用预定义命名的函数回调参数。 我白天是一个Java程序员,并丢弃关于企业-Y名称刻板刺戳为代码单元的我是来享受一个语言与特性吧IDE的强大的选择工作的事情之一是,用有意义的,如果长时间,名称可以使代码的意图和意义,而不使之更难以真正成为生产力更加清晰。 那么,为什么编写JavaScript代码时没有使用相同的方法?

给它想,我能想出是支持和反对这个想法两种观点,但我的天真和新奇的语言损害我从达成任何结论,为什么这将是很好的在技术层面。

优点:

  • 灵活性。 有一个回调参数异步函数可以通过许多不同的代码路径之一到达,它可以被忙碌的有写一个名为函数来考虑每一个可能的边缘情况。
  • 速度。 它起着巨资到黑客的心态。 到它,直到它的工作原理博尔特的事情。
  • 其他人是做什么的
  • 较小的文件,即使如此平凡,但每一个位在网络上计数。
  • 简单的AST? 我会假设,匿名函数是在运行时生成,并因此JIT不会与名称映射到指令渣土约,但我只是在这一点猜测。
  • 更快的调度? 不知道这一个无论是。 再次猜测。

缺点:

  • 这是可怕的和不可读
  • 它增加了混乱,当你嵌套坚果深回调的沼泽(其中,说句公道话,大概意思是你写的结构不佳的代码开始,但它是很常见的)。
  • 对于有人没有功能的背景也可以是一个奇怪的概念神交

有了这么多的现代浏览器显示执行JavaScript代码比以前快得多的能力,我没有看到任何琐碎之类的性能如何获得一个可能会失去使用匿名回调将是一种必然。 看来,如果你是在一个情况下使用命名的功能是可行的(可预测的行为和执行的路径),那么也就没有理由不这么做。

那么,有没有我不知道的,使这种做法非常普遍的一个原因,任何技术原因还是陷阱?

Answer 1:

我用匿名函数的原因有三:

  1. 如果不需要名字,是因为该功能只能用在一个地方叫,那么为什么名称添加到你在任何命名空间。
  2. 匿名函数内联声明和内联函数必须在他们可以在父范围内访问变量的优势。 是的,你可以把一个匿名函数的名称,但如果它内联声明这通常是没有意义的。 所以内嵌有显著的优势,如果你正在做内联,有什么理由把一个名字就可以了。
  3. 当处理程序是在呼唤他们的代码中正确定义的代码似乎更自足性和可读性。 你可以阅读几乎顺序的方式代码,而不是去发现与名称的功能。

我也尽量避免匿名函数深度嵌套,因为那可能是毛茸茸的理解和阅读。 出现这种情况通常情况下,有一种更好的方法来组织代码(有时一个循环,有时一个数据表,等...),并命名功能,通常不存在的解决办法。

我想我补充一点,如果回调开始变得比约15-20线长更和它并不需要在父范围内直接访问变量,我会受到诱惑,给它一个名称,并打破它伸到这是其他地方宣布自己命名的功能。 肯定这里有可读性的地步,如果它放在自己的命名单元,获得长一个不平凡的功能仅仅是更容易维护。 但是,大多数的回调我最终没有那么长,我觉得它更具可读性,让他们在线。



Answer 2:

我更喜欢叫自己的功能,但对我来说它归结为一个问题:

我将使用这个函数在其他地方?

如果答案是肯定的,我的名字/定义它。 如果没有,把它作为一个匿名函数。

如果你只使用一次,它没有意义的人群全局命名空间吧。 在当今复杂的前端,这本来是匿名的命名函数的数量增长很快(很容易超过1000对真正复杂的设计),导致(相对)由宁愿匿名函数大的性能提升。

然而,代码的可维护性也是非常重要的。 每一种情况是不同的。 如果你不写了很多的这些功能,首先,有一个在做两种方式都没有坏处。 这真的取决于你的喜好。

另一个需要注意的有关名称。 获取定义长名称的习惯,真的会伤害你的文件的大小。 看看下面的例子。

假设这两个函数做同样的事情:

function addTimes(time1, time2)
{
    // return time1 + time2;
}

function addTwoTimesIn24HourFormat(time1, time2)
{
    // return time1 + time2;
}

第二个告诉你正是它的名字。 首先是比较模糊的。 不过,也有在名称差异的17个字符。 说的功能在整个代码中调用的8倍,这是你的代码并不需要有153个额外的字节 。 没有巨大的,但如果它是一个习惯,即推断为10秒,甚至功能100S容易意味着在下载差异的几KB。

但是同样,可维护性需要对性能带来的好处进行权衡。 这是处理一个脚本语言的痛苦。



Answer 3:

有点迟到了,但有些没有提到方面的功能,匿名或以其他方式...

匿名funcs中不容易被提及的有关代码人形的对话,其中包括一队。 例如,“乔,你能解释的算法做了什么,该函数内。......哪一个?在fooApp函数中的第17次匿名函数。......不,不是那一个!第17届一个!”

匿名funcs中是匿名的调试器为好。 (废话!)因此,调试堆栈跟踪通常只显示一个问号或相似,使得当您设置多个断点它用处不大。 你碰到了断点,但发现自己滚动调试窗口向上/向下揣摩出你到底是在你的程序,因为嘿,问号功能只是没有做到这一点!

关于污染全局命名空间的担忧是有效的,但在命名的功能你自己的根对象中的节点容易补救,如“myFooApp.happyFunc =功能(...){...};”。

函数是在全局命名空间,或在你的根对象像上面的节点,可以从调试器直接开发和调试过程中调用。 例如,在控制台的命令行中,执行“myFooApp.happyFunc(42)”。 这是不存在的(本地)在编译的编程语言一个非常强大的能力。 尝试与一个匿名FUNC。

匿名funcs中可以由通过将它们分配到一个var和然后使VAR作为回调(而不是内联)更具有可读性。 例如:VAR =时髦功能(...){...}; 。jQuery的( '#奥的斯')点击(时髦);

使用上面的方法,你可以在父母的FUNC的顶部,然后在其下方,顺序语句的肉变得更严格的分组,更易于阅读的潜在组几个匿名funcs中。



Answer 4:

那么,仅仅是明确针对我的论点起见,以下都是匿名函数/在我的书函数表达式:

var x = function(){ alert('hi'); },

indexOfHandyMethods = {
   hi: function(){ alert('hi'); },
   high: function(){
       buyPotatoChips();
       playBobMarley();
   }
};

someObject.someEventListenerHandlerAssigner( function(e){
    if(e.doIt === true){ doStuff(e.someId); }
} );

(function namedButAnon(){ alert('name visible internally only'); })()

优点:

  • 它可以减少一点克鲁夫特的,特别是在递归函数(在那里你可以(实际上应该因为arguments.callee的已废弃)仍然使用每内部的最后一个例子名为基准),并明确功能永远只能触发在这一个地点。

  • 代码可读性取胜:在对象字面与被指定为方法匿名funcs中的例子,那将是愚蠢的,添加更多的地方在你的代码狩猎和啄逻辑当对象文本的全部意义在于扑通一些相关的功能在同样方便参考点。 当声明在构造函数中的公共方法,但是,我不倾向于内联定义标记功能,然后指定为this.sameFuncName的引用。 它让我在内部使用相同的方法,没有“这一点。” 克鲁夫特,使定义的顺序时,他们互相称呼非担忧。

  • 有用的,以避免不必要的全局命名空间的污染 - 内部命名空间,但是,不应该永远是广泛填充或处理由多个团队同时进行,这样说法似乎有点傻我。

  • 我设置短的事件处理程序时,使用inline回调同意。 这是愚蠢的有去寻找一个1-5线功能,尤其是与JS和功能提升,定义最终可能会在任何地方,甚至没有在同一个文件。 这可能是偶然发生没有什么突破,没有,你并不总是有这些东西的控制。 活动总是导致一个回调函数被解雇。 我们没有理由要更多的链接添加到您需要通过只是为了扭转在一个大的代码库和堆栈跟踪关注工程师简单的事件处理程序可以通过抽象事件触发自己变成当调试日志有用的信息的方法来解决扫描名称链模式是与火的触发器。 实际上,我开始构建整个界面这个样子。

  • 用于需要函数定义的顺序关系。 有时候,你想成为某些默认的功能是什么,你认为它是在之前的代码一定地步,没关系重新定义它。 或者你想破损更加明显,当依赖获得洗牌。

缺点:

  • 匿名函数不能采取功能提升的优势。 这是一个重大的区别。 我倾向于采取提升确定自己明确命名funcs中和对象构造朝下方,并获得了对象定义和主环型的东西的权利在最顶端的重优势。 我发现它使代码更易于阅读时,你的名字你瓦尔情况良好,获得CTRL-Fing头之前发生了什么事情的细节时,才不管你的视野开阔。 吊装也可以在大量事件驱动接口一个巨大的好处在那里实行的什么可用时会咬你的屁股严格的秩序。 起重都有自己的注意事项(如圆形基准电位),但它是为组织和使用权当使代码清晰的一个非常有用的工具。

  • 可读性/调试。 当然他们习惯的方式太重,有时它可以使调试和代码的可读性麻烦。 严重依赖JQ代码库,例如,可以是一个严重的PITA阅读和调试,如果你不封装的$汤近必然匿名重型和大型重载ARGS一个明智的方式。 JQuery的例如悬停的方法,是过度使用匿名funcs中的一个经典的例子,当你把2个匿名funcs中到它,因为它很容易为第一个定时器假设它是一个标准的事件侦听器分配方法,而不是一个方法重载分配处理一个或两个事件。 $(this).hover(onMouseOver, onMouseOut)是很多超过两个匿名funcs中更加清晰。



Answer 5:

其更具有可读性使用命名功能,它们也能够自引用的如在下面的例子。

(function recursion(iteration){
    if (iteration > 0) {
      console.log(iteration);
      recursion(--iteration);
    } else {
      console.log('done');
    }
})(20);

console.log('recursion defined? ' + (typeof recursion === 'function'));

http://jsfiddle.net/Yq2WD/

当你想有一个立即调用函数引用本身,但不添加到全局命名空间,这是很好的。 它仍然可读,但不会产生污染。 有你的蛋糕,它吃。

嗨,我的名字是贾森或Hi,我的名字是???? 你选。



文章来源: What are the benefits to using anonymous functions instead of named functions for callbacks and parameters in JavaScript event code?