条件运算符===
与赋值运算符=
之间的性能是否存在差异?我正在用猫鼬写一些预先保存的钩子中间件,我想知道它们之间是否存在很大的速度差异:
UserSchema.pre('save', function (next) {
if (!this.isModified()) {
return next();
}
this.crm.isUpToDate = false;
next();
});
和
UserSchema.pre('save', function (next) {
if (!this.isModified()) {
return next();
}
if (this.crm.update === true) {
this.crm.isUpToDate = false;
}
next();
});
编辑:
感谢您的建设性意见。
基本上,它看起来并没有太大的性能差异(如上所述它可以忽略不计)。感谢用于测试速度http://jsperf.com/的酷工具,我以前从未听说过它。
对于那些对这些代码感到疑惑的人,首先我在原帖中犯了一个明显错误,然后当每个人都试图向我指出时我哭了,这可能是每个人都投票的原因。
这是我正在做的事情:
我有一个mongoose预保存中间件挂钩(用于mongo数据库),每次保存文档时都会运行挂钩。在保存时,我检查文档是否已更新。如果是,我将crmIsUpToDate
设置为false。当cron作业到达时,crmIsUpToDate
将设置为true。在cron作业到达文档之前,可以多次运行此挂钩。
我认为这不是问题所必需的,因为问题在于进行比较===
和做作业=
之间是否存在差异。我甚至不应该把代码放上去,因为它确实减少了主要问题。
答案 0 :(得分:45)
如果您使用非引用语言(JavaScript不是)并执行大对象的赋值('=',导致复制操作),则可能会“慢”。因此,检查是否真的需要复制操作可以为您节省大量时间。
但JavaScript是一种本机引用语言:
object1 = {a: 1, b: 2};
object2 = object1; // refcounting copy?
object1.a = 3; // test by modifying the first object
console.log( object2.a ); // will return 3 => refcounting
=>所以所有赋值操作('=')都很便宜。
而且,更重要的是,您正在使用本机数据类型(bool,数字将是相同的),可能更快或至少与对象一样快。
注意:字符串不会在JavaScript中重新计算,在这种情况下它们是一个例外。
所以,现在我们已经知道这项任务很便宜。但身份检查怎么样('===')?
在您的代码中,您必须绕过对象this
- > crm
- > update
- 这需要一些额外的时间。然后必须检查类型(bool)的相同性,然后检查内容(false)是否相同
所有这些都是在程序流程中添加条件,其中具有长管道的现代CPU可能会猜测分支错误地创建停顿并重新加载整个管道。这也浪费了相当多的CPU周期(尽管现代CPU在这方面相当不错)。
=>这种比较('===')相当昂贵。
结论#1:
您不应该通过可以轻松避免的昂贵测试来保护廉价代码
当代码变得更加昂贵时,测试将在最后节省时间。这导致:
结论#2:
过早优化是邪恶的!它可以使代码更难阅读,引入新的错误,使代码更大(也有利于缓存效率),...
=>只优化您确定在性能问题中运行的代码部分 - 然后仅基于分析信息。人类在这里猜测效果是非常糟糕的......
答案 1 :(得分:1)
当前的最高答案在一个重要点上是不正确的:===
与=
类似,因为它没有深入地比较对象;它只是检查它们是否引用内存中的同一对象。 (if
分支是这里唯一的真正罪魁祸首)
条件运算符
===
和赋值运算符=
之间的性能是否有区别?
===
不是条件运算符-===
是“严格相等比较”(或“标识”或“严格等于”)。 (JavaScript的条件运算符的格式为condition ? expr1 : expr2
)
已经知道使用varName = expression
进行分配非常便宜:本质上,它获取expression
在内存中的位置,并使varName
也指向该位置。即使expression
是一个巨大的对象,也不会发生深层复制。
但是对于严格平等比较而言,同样的情况也是如此,在大多数情况下-expr1 === expr2
在以下任一情况下均将得出true
:
两个表达式都是基元,并且都具有相同的类型和相同的值(NaN
除外),或者
两个表达式都是对象,并且这些对象是内存中的相同对象。
检查两个对象表达式是否引用内存中的同一对象非常便宜-与获取对象的内存引用并具有指向该内存位置的可变点(如=
的数量级相同确实)。 ===
不会深入比较每个嵌套的属性和值(除非您通过JSON.stringify
两侧的===
进行显式比较,但在这种情况下,瓶颈是{{ 1}},而不是JSON.stringify
)
带有===
分支的代码:
if
会比普通作业慢:
if (this.crm.update === true) {
this.crm.isUpToDate = false;
}
因为逻辑分支较慢(相对); this.crm.isUpToDate = false;
检查和===
分配非常快:
一般而言,分支比直线代码(在所有CPU上以及所有编程语言中)慢。 -jmrk, V8 developer
这是著名问题:Why is it faster to process a sorted array than an unsorted array?
背后的相同问题也就是说,尽管逻辑分支确实需要额外的资源,但是在现代计算机上,效果很少显着-争取使用干净,可读的代码更好,并且只考虑更改 >在确定该段会导致性能瓶颈之后,否则,由于通常难以察觉的差异,您将使代码难以阅读。