在while循环条件中使用赋值表达式是一种不好的做法?

3

本文解释了为什么在使用像这样的代码时会出现警告:

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条件中赋值表达式是一种不好的做法?”。

我也看到了Stack Overflow的答案,认为这种做法是好的。那么...

while (element = element.parentNode)语法是否存在性能问题或只是一种代码风格建议?


顺便提一下,“--i”运算符也是一种不好的做法。我在这篇文章中看到

++(增量)和--(减量)运算符因鼓励过度狡猾而被认为对糟糕的代码有所贡献。

可能这是某种玩笑吧?

2个回答

7

这个操作不应该有性能问题(可以争论,使用前置递增的索引可能略慢于后置递增,由于CPU管道的问题;这是微观优化,微得近乎无意义,即使在C语言中编译器也会重新排列表达式以确保它不会因等待递增而停顿)。

无论哪种方式,在条件语句中进行赋值的主要争议点基本上是,大多数情况下,当你这样做时,这是一个错误(你的意思可能是 == 或者在JS中,是 ===)。一些代码检查器(C#需要这个作为语言特性来避免意外)会满意地接受您将赋值包装在额外的括号中,以表明“是的,我真的想赋值”(当您将赋值的结果与其他值进行比较时,这也是必需的;省略括号会相反地进行比较,然后分配一个布尔值,这更可能是错误的)。

有些人对作为较大表达式一部分使用的增量/减量运算符很讨厌,因为记住运算顺序很难,我猜是因为C程序员已经知道如何编写可怕的代码,例如 ++*++var 等。我忽略这些人;只要不用于过于棘手的事情即可。


把你可能用 = 而不是 == 的错误指出来是有意义的。但是关于赋值性能(而不是前缀/后缀递增性能),也没有性能问题吗? - Bruno J. S. Lesieur
1
@Haeresis:它可能存在的任何问题,要么微不足道,要么可以通过编译器重新排序在任何合理现代JS引擎上消除。唯一可能有帮助(请进行分析!)的是明确测试 while ((htmlElement = htmlCollection[--i]) !== undefined),这可能会为JS JIT-er提供足够的信息来将表达式优化为简单的指针比较,但同样,在JS开销的情况下,这是一个微小的优化,不太可能产生影响。 - ShadowRanger
谢谢,我没问题。 - Bruno J. S. Lesieur

0
作为一种正交方法,也可能是更加“清晰/简洁”的方法,有以下内容:
// 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 可以避免这种情况,但我不确定。 - Bruno J. S. Lesieur
@Haeresis:它并不能避免这个问题。另一方面,切换到 document.querySelectorAll('.class-name') 将会避免这个问题,因为该函数返回的 NodeList 是一个快照而不是实时视图。 - ShadowRanger
是的。它只是慢一些(http://codepen.io/Haeresis/pen/epQLBG 和 http://codepen.io/Haeresis/pen/epQLve);p 谢谢! - Bruno J. S. Lesieur
有了ES6的of而不是in,就不需要使用一些hasOwnProperty检查了吗? - Bruno J. S. Lesieur
使用.target而不是.vanilla .inner div,可以通过getElementsByClassName获得2倍的性能提升。但是如果进行反向迭代,则性能会降低0.5倍,这是相同的情况 :) - Bruno J. S. Lesieur
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接