什么是没有操作的JavaScript约定?

什么是没有操作的JavaScript约定?

  • 一个选项只是一个空的函数: function() {}
  • jQuery提供$.noop() ,它只是简单地调用上面的空函数。
  • 简单地input一个false0的值是可以接受的吗?

在上下文中…所有这些工作没有在Chrome中抛出一个错误:

 var a = 2; (a === 1) ? alert(1) : function() {}; (a === 1) ? alert(1) : $.noop(); (a === 1) ? alert(1) : false; (a === 1) ? alert(1) : 0; 

编辑:很多人回应,“不要这样做!改变代码结构! 这让我想起了一个有人问如何嗅探浏览器的post。 他收到了大量的post,说:“不要这样做!这是邪恶的,”但没有人告诉他如何嗅探浏览器 。 这不是代码审查。 想象一下,你正在处理遗留的代码,不能改变,没有传入一些function,它会抛出一个错误。 或者,简单想象一下,如果这是客户想要的方式 。 所以,敬请回答以下问题 :在JavaScript中指定“无操作”function的最佳方法是什么?

编辑2:其中之一呢?

 true; false; 0; 1; null; 

为了回答最初的问题,纯Javascript中的noop函数的最优雅和整洁的实现(如这里也讨论的)是Function.prototype 。 下面的代码显示了它的用法:

 setTimeout(Function.prototype, 10000); 

所有三个浏览器(Chrome,Firefox和IE 11)在执行上述操作10秒后都不会导致解释器回来(可以使用debugging器中的“step over”模式逐步testing)。

虽然这是一个“真正的noop”,因为大多数浏览器似乎没有办法执行这样定义的noop(并因此节省CPU周期),可能会有一些与此相关的性能问题(正如其他人在评论中或其他答案)。

然而,这就是说,你可以很容易地定义自己的noop函数,事实上,许多库和框架也提供noop函数。 以下是一些例子:

 var noop = function () {}; // Define your own noop in ES3 or ES5 const noop = () => {}; // OR Define your own noop in ES6 setTimeout(noop, 10000); // Using the predefined noop setTimeout(function () {} , 10000); // Using directly in ES3 or ES5 setTimeout(() => {} , 10000); // Using directly in ES6 as Lambda (arrow function) setTimeout(angular.noop, 10000); // Using with angular 1.x setTimeout(jQuery.noop, 10000); // Using with jQuery 

下面是noop函数(或相关讨论或谷歌search)的各种实现的按字母顺序排列的列表:

Angular 1.xAngular 2+ (似乎没有本地实现 – 使用你自己的如上所示), EmberjQueryLodashNodeJSRamdaReact (似乎没有本地实现 – 使用你自己的如上所示), RxJS下划线

底线 :虽然Function.prototype是在Javascript中expression一个noop的优雅方式,但是,可能会有一些性能问题与它的使用有关。 所以,你可以定义和使用你自己的(如上所示),或者使用你在代码中使用的库/框架定义的一个。

不会比调用() => {}简单得多。

它在你的浏览器中工作(如果没有,在一个月内回来)。

编辑: () => {}甚至可能比Function.prototype运行得更快 ,具体取决于您的环境。 下面的testing表明,即使浏览器被允许升级后者,前者在Chrome 55中的运行速度始终快于20%。

 const noop = () => {} const noopProto = Function.prototype function test (_noop, iterations) { const before = performance.now() for(let i = 0; i < iterations; i++) _noop() const after = performance.now() const elapsed = after - before console.info(`${elapsed.toFixed(4)}MS\t${_noop.toString().replace('\n', '')}\tISNOOP? ${_noop() === undefined}`) } const iterations = 10000000 console.info(`==NOOP TEST @ ${iterations.toLocaleString()}==`) test(noop, iterations) test(noopProto, iterations) 

无论你在这里达到什么目的都是错误的。 三元expression式不能作为一个完整的陈述,只能用于expression,所以你的问题的答案是:

没有你的build议,而是做:

 var a = 2; if (a === 1) alert(1) // else do nothing! 

那么代码很容易理解,可读性和尽可能高效。

为什么使它变得更加困难,何时可以变得简单?

编辑:

那么,一个“无操作”的命令是否基本上代表了一个劣质的代码结构呢?

你错过了我的观点。 以上都是关于三元expression式x ? y : z x ? y : z

但是,在Javascript等高级语言中,没有操作命令是没有意义的。

它通常用于较低级别的语言,如汇编或C语言,这是为了使处理器对于一个指令进行计时而不做任何事情。

在JS中,你是否做0;null;function () {}; 或者是一个空的陈述,那么解释者在阅读时就会忽略它,但是它被解释之前 ,所以最终只会让你的程序加载得更慢一些的时间。 Nota Bene :我假设这一点,因为我没有参与任何广泛使用的JS解释器,每个解释器都有自己的策略。

如果你使用一些更复杂的东西,比如$.noop()var foo = function () {}; foo() var foo = function () {}; foo() ,那么解释器可能会做一个无用的函数调用,最终会损坏你的函数堆栈的几个字节,以及几个周期。

我看到$.noop()这样的函数的唯一原因是存在的,那就是仍然可以给一些事件函数提供一个callback函数,如果它不能调用这个callback函数,就会抛出一个exception。 但是,这必然是一个你需要给予的function,给它noop名字是一个好主意,所以你告诉你的读者(也许你在6个月内),你故意给一个空的函数。

最后,没有“劣等”或“优”的代码结构。 你使用你的工具的方式是正确的或错误的。对你的例子使用三元组就像使用锤子,当你想拧。 它会工作,但你不确定你可以挂在螺丝上的东西。

什么可以被认为是“劣势”或“优越”是你在代码中的algorithm和想法。 但那是另一回事

我认为,jQuery的noop()主要是为了防止代码崩溃通过提供一个默认的function,当请求的不可用。 例如,考虑下面的代码示例,如果没有定义$.noop则select$.noop ,防止下一次fn调用崩溃:

 var fn = fakeFunction || $.noop; fn() // no crash 

然后, noop()允许通过避免在代码中的任何地方多次写入相同的空函数来节省内存。 顺便说一下, $.noopfunction(){} (每个标记保存6个字节function(){}短一些。 所以,你的代码和空函数模式之间没有任何关系。 使用nullfalse0如果你喜欢,在你的情况下将不会有副作用。 此外,值得注意的是,这个代码…

 true/false ? alert('boo') : function(){}; 

…完全没用,因为你永远不会调用这个函数,而这个…

 true/false ? alert('boo') : $.noop(); 

…因为你调用了一个空的函数,所以它更加无用

 true/false ? alert('boo') : undefined; 

让我们用if语句replace三元expression式,看看它有多less是无用的:

 if (true/false) { alert('boo'); } else { $.noop(); // returns undefined which goes nowhere } 

你可以简单地写:

 if (true/false) alert('boo'); 

甚至更短:

 true/false && alert('boo'); 

为了最终回答你的问题,我想“传统的无操作”是永远不会写的。

我用:

  (0); // nop 

要testing此运行的执行时间为:

 console.time("mark"); (0); // nop console.timeEnd("mark"); 

结果:标记:0.000ms

使用Boolean( 10 > 9)可以简化为( 10 > 9) ,它返回true 。 使用单个操作数的想法,我完全期待(0); 将返回false ,但它只是简单地返回参数,可以通过在控制台执行此testing来查看。

 > var a = (0); < undefined > a < 0