while 条件中的赋值表达式是一种不好的做法?

Posted

技术标签:

【中文标题】while 条件中的赋值表达式是一种不好的做法?【英文标题】:Assignment expression in while condition is a bad practice? 【发布时间】:2016-04-10 14:54:42 【问题描述】:

This article 解释了为什么我在使用这样的代码时会收到警告:

var htmlCollection = document.getElementsByClassName("class-name"),
    i = htmlCollection.length,
    htmlElement;

// Because htmlCollection is Live, we use a reverse iteration.
while (htmlElement = htmlCollection[--i])  // **Warning?! Why?!**
    htmlElement.classList.remove("class-name");

但这没有解释«为什么在while条件下赋值表达式是一种不好的做法? »。

我还阅读了这个*** answers,指出这种做法同样好。所以...

while (element = element.parentNode) 语法有性能问题还是只是样式代码建议?


顺便说一句,似乎«--i » 运算符也是一种不好的做法。我read in this article:

众所周知,++(递增)和 --(递减)运算符会通过鼓励过多的技巧来导致不良代码。

这是什么玩笑?

【问题讨论】:

【参考方案1】:

它应该没有性能问题(可以说,由于 CPU 管道的问题,使用前缀增量的索引可能比后缀增量稍慢;这是一个微优化,非常微不足道,几乎可以肯定它在上下文中毫无意义JS 引擎开销,即使在 C 语言中,编译器也可能会重新排序表达式,以确保它不会因等待增量而停滞)。

无论哪种方式,反对条件赋值的主要论点基本上是大多数当你这样做时,这是一个错误(你的意思是==或在JS中,===) .如果您将分配包装在额外的括号中,那么某些代码检查器(C# 要求将其作为语言功能以避免事故)会感到满意,例如“是的,我真的打算分配”(当您'重新将分配的结果与其他值进行比较;省略括号会改为比较,然后分配一个布尔值,这更可能是错误的)。

有些人讨厌用作较大表达式的一部分的递增/递减运算符,因为我猜很难记住操作的顺序,而且众所周知,C 程序员会写出可怕的东西,比如++*++var 之类的东西。我忽略了这些人;只是不要将它用于过于棘手的事情。

【讨论】:

这表明你有“可能”使用= 而不是== 出错。但是关于赋值性能(不是前缀/后缀增量性能),也没有性能问题? @Haeresis:它可能存在的任何问题都可以忽略不计,或者通过编译器在任何合理的现代 JS 引擎上重新排序来消除。唯一可能帮助(配置文件!)的事情是显式测试while ((htmlElement = htmlCollection[--i]) !== undefined),这可能为 JS JIT-er 提供足够的信息以将表达式优化为简单的指针比较,但同样,在 JS 开销的情况下,这是一个不太重要的微优化。 谢谢,我没问题。【参考方案2】:

作为一种正交方法,并且可能“更清晰/更清晰”:

// var htmlCollection = document.getElementsByClassName("class-name");
var htmlCollection = document.querySelectorAll('.class-name');
for(let htmlElement of htmlCollection) 
     htmlElement.classList.remove("class-name");

作为一种遍历 DOM 元素的方法。

已更新以包含来自以下 ShadowRanger 的建议。

【讨论】:

这个方法不是反向迭代吗?所以我不能在这种特殊情况下使用它,因为如果我删除class-name,该项目将从 Live htmlCollection 中删除,下一个项目不是 n+1 而是 n+2。也许of 避免这种情况,但我不这么认为。 @Haeresis:这并不能避免。另一方面,切换到document.querySelectorAll('.class-name') 会避免它,because the NodeList returned by that function is a snapshot, not a live view。 是的。只是更慢(codepen.io/Haeresis/pen/epQLBG 和 codepen.io/Haeresis/pen/epQLve);p 谢谢! 而用这个 ES6 of 代替 in,是不是需要用一些hasOwnProperty 检查? @Haeresis:那个测试不是苹果对苹果;您的 querySelectorAll 正在执行基于后代的额外过滤;这会花费时间,而且您不会弥补,因为您从不使用结果(大概您必须手动执行子查询才能获得每个 .vanilla.inner div 后代。querySelectorAll 几乎如果您要跟进 getElementsByClassName 对每个结果的子查询,肯定会赢得 getElementsByClassName

以上是关于while 条件中的赋值表达式是一种不好的做法?的主要内容,如果未能解决你的问题,请参考以下文章

匿名函数在 JavaScript 中是一种不好的做法吗?

使用“?”是一种不好的做法。在 Racket 方法名称中?

使用 Java 的默认包是一种不好的做法吗?

为啥直接从 Servlet 访问 DAO 是一种不好的做法?

为啥使用“评估”是一种不好的做法?

JavaScript:动态扩展原型是一种不好的做法吗?