无操作的JavaScript约定是什么?
function() {}
$.noop()
,它只是调用上面的空函数。false
或0
的值即可接受? 在上下文中...所有这些工作都没有在Chrome中引发错误:
var a = 2;
(a === 1) ? alert(1) : function() {};
(a === 1) ? alert(1) : $.noop();
(a === 1) ? alert(1) : false;
(a === 1) ? alert(1) : 0;
编辑:很多人回答说,“不要这样做!改变代码结构!”这让我想起了有人问如何嗅探浏览器的帖子。他接到一连串的帖子说:“不要那样做!它是邪恶的”,但没有人告诉他如何嗅探浏览器。这不是代码审查。想象一下,您正在处理无法更改的遗留代码,如果没有传入某些函数,它将丢失一个错误。或者,简单地说,这就是客户想要的方式,他们付钱给我。所以,请尊重回答问题:在JavaScript中指定“无操作”功能的最佳方法是什么?
EDIT2:其中一个怎么样?
true;
false;
0;
1;
null;
答案 0 :(得分:77)
要回答原始问题,纯Javascript中的noop函数的最优雅和最简洁的实现(正如也讨论here)是 Function.prototype 。下面的代码段显示了它的用法:
setTimeout(Function.prototype, 10000);
执行上述操作后,所有三个浏览器(Chrome,Firefox和IE 11)都不会导致解释程序在10秒后返回(您可以使用&#34步骤测试;在调试器中跳过"模式)
虽然这是一个真正的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
以下是各种函数(或相关讨论或谷歌搜索)的各种实现的按字母顺序排列的列表:
Angular 1.x, Angular 2+ (似乎没有原生 实施 - 使用您自己的,如上所示),Ember,jQuery,Lodash,NodeJS,Ramda, React (似乎没有原生实现 - 如上所示使用您自己的实现),RxJS, Underscore
BOTTOM LINE :虽然Function.prototype是一种在Javascript中表达noop的优雅方式,但是可能存在与其使用相关的一些性能问题。因此,您可以定义和使用自己的(如上所示)或使用您可能在代码中使用的库/框架定义的文件。
答案 1 :(得分:38)
最简洁,最高效的noop是空箭头功能:()=>{}
。
Arrow functions在除IE以外的所有浏览器中原生工作(如果必须,还有babel transform):
()=>{}
与Function.Prototype
()=>{}
比Chrome 67中的Function.prototype
<强> 87%。()=>{}
比Firefox 60中的Function.prototype
快25%。()=>{}
比Edge (6/15/2018)中的Function.prototype
<85>快。()=>{}
比Function.prototype
少<65%的代码。下面的测试使用箭头函数加热以向Function.prototype
提供偏差,但箭头功能是明显的赢家:
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}`);
return elapsed;
}
const iterations = 10000000
console.info(`noop time for ${iterations.toLocaleString()} iterations`)
const timings = {
noop: test(noop, iterations),
noopProto: test(noopProto, iterations)
}
const percentFaster = ((timings.noopProto - timings.noop)/timings.noopProto).toLocaleString("en-us", { style: "percent" });
console.info(`()=>{} is ${percentFaster} faster than Function.prototype in the current browser!`)
&#13;
答案 2 :(得分:15)
无论你在这里取得什么成就都是错误的。三元表达式不得用作完整语句,仅用于表达式,因此您的问题的答案是:
没有你的建议,而是:
var a = 2;
if (a === 1)
alert(1)
// else do nothing!
然后代码很容易理解,可读并且尽可能高效。
为什么在简单的时候让它变得更难?
编辑:
那么,“无操作”命令是否基本上表明了较差的代码结构?
你错过了我的观点。以上所有内容都是关于三元表达式x ? y : z
。
但是,在诸如Javascript之类的高级语言中,没有操作命令是没有意义的。
它通常用于较低级语言(如汇编语言或C语言),作为使处理器不为一条指令执行任何操作以进行计时的方法。
在JS中,无论你是0;
,null;
,function () {};
还是空语句,解释器在阅读它时都会很有可能忽略它,但是之前它被解释,所以最后,你只需要在很短的时间内加载你的程序。 Nota Bene :我假设这一点,因为我没有参与任何广泛使用的JS解释器,并且每个解释器都有可能有自己的策略。
如果你使用更复杂的东西,比如$.noop()
或var foo = function () {}; foo()
,那么解释器可能会执行一个无用的函数调用,最终会破坏函数堆栈的几个字节,并且几个周期。
我看到$.noop()
这样的函数存在的唯一原因就是能够仍然给某些事件函数提供一个回调函数,如果它不能调用该回调就会引发异常。但是,它必然是你需要给予的一个功能,给它noop
这个名字是一个好主意,所以你告诉你的读者(可能是你在6个月内),你故意给出一个空功能
最后,没有“劣质”或“优越”的代码结构。你使用工具的方式要么是对的。使用三元作为你的例子就像在你想要拧螺丝时使用锤子。它会工作,但你不确定你可以挂在那个螺丝上。
可以认为“劣等”或“优越”的是您在代码中添加的算法和想法。但那是另一回事。
答案 3 :(得分:6)
我认为jQuery noop()
主要是为了防止代码在请求的默认功能不可用时提供默认功能而崩溃。例如,考虑以下代码示例,如果未定义$.noop
,则会选择fakeFunction
,以防止下一次调用fn
崩溃:
var fn = fakeFunction || $.noop;
fn() // no crash
然后,noop()
允许通过避免在代码中的任何地方多次写入相同的空函数来节省内存。顺便说一句,$.noop
比function(){}
略短(每个令牌节省6个字节)。因此,您的代码与空函数模式之间没有关系。如果您愿意,可以使用null
,false
或0
,在您的情况下,不会产生任何副作用。此外,值得注意的是这段代码......
true/false ? alert('boo') : function(){};
...完全没用,因为你永远不会打电话给这个功能,而这个......
true/false ? alert('boo') : $.noop();
...因为你调用一个空函数更加无用,这与...完全相同。
true/false ? alert('boo') : undefined;
让我们用if
语句替换三元表达式,看看它有多大用处:
if (true/false) {
alert('boo');
} else {
$.noop(); // returns undefined which goes nowhere
}
你可以写一下:
if (true/false) alert('boo');
甚至更短:
true/false && alert('boo');
为了最终回答你的问题,我认为“传统的无操作”是从未写过的。
答案 4 :(得分:3)
我用:
(0); // nop
将此次运行的执行时间测试为:
console.time("mark");
(0); // nop
console.timeEnd("mark");
结果:标记:0.000ms
使用Boolean( 10 > 9)
可以将其简化为只返回( 10 > 9)
的{{1}}。提出使用单个操作数的想法我完全期望true
将返回(0);
,但它只是返回参数,因为可以通过在控制台上执行此测试来查看。
false
答案 5 :(得分:2)
在Function.prototype
上使用() => {}
绝对没有问题或性能损失。
Function.prototype
的主要好处是拥有单例函数,而不是每次都重新定义一个新的匿名函数。在定义默认值并进行记录时,使用像Function.prototype
这样的no-op尤为重要,因为它为您提供了一个永不改变的一致对象指针。
我之所以推荐Function.prototype
而不是Function
是因为它们不相同:
Function() === Function()
// false
Function.prototype() === Function.prototype()
// true
另外,其他答案中的基准具有误导性。实际上,Function.prototype
的性能要比() => {}
更快,这取决于编写和运行基准测试的方式:
You can’t trust JS benchmarks <<明确指出了这个问题的基准。
不要根据基准设置代码样式;做任何可维护的事情,让解释器弄清楚从长远来看如何进行优化。