jslint工具的一个提示是:

++和—— ++(递增)和——(递减) 众所周知,操作符会导致糟糕的代码 鼓励过度狡诈。他们 仅次于有缺陷的架构 使病毒和其他 安全威胁。这是一个加分项 选项,禁止使用这些 操作符。

我知道PHP结构像$foo[$bar++]可能很容易导致off-by-one错误,但我想不出一个更好的方法来控制循环比:

while( a < 10 ) do { /* foo */ a++; }

or

for (var i=0; i<10; i++) { /* foo */ }

jslint突出显示它们是因为有一些类似的语言缺少“++”和“——”语法或处理方式不同,还是有其他避免“++”和“——”的理由,我可能忽略了?


当前回答

避免使用++或——的最重要理由是,操作符返回值的同时会引起副作用,使代码更难推理。

为了效率考虑,我倾向于:

++i当不使用返回值时(无临时) 当使用返回值时i++(没有管道停顿)

我是克罗克福德先生的粉丝,但在这件事上我不同意。++i要解析的文本比i+=1少25%,可以说更清晰。

其他回答

Fortran是一种类c语言吗?它既没有++也没有——。下面是如何编写循环:

     integer i, n, sum

      sum = 0
      do 10 i = 1, n
         sum = sum + i
         write(*,*) 'i =', i
         write(*,*) 'sum =', sum
  10  continue

索引元素i在每次循环中都按语言规则递增。如果你想增加除1以外的值,例如向后数2,语法是…

      integer i

      do 20 i = 10, 1, -2
         write(*,*) 'i =', i
  20  continue

Python像c语言吗?它使用范围和列表推导式以及其他语法来绕过对索引增量的需要:

print range(10,1,-2) # prints [10,8.6.4.2]
[x*x for x in range(1,10)] # returns [1,4,9,16 ... ]

因此,基于对这两种替代方案的初步探索,语言设计人员可以通过预测用例并提供替代语法来避免++和——。

相比拥有++和——的过程式语言,Fortran和Python是否更少吸引bug ?我没有证据。

我之所以说Fortran和Python是类似C语言的语言,是因为我从来没有遇到过一个精通C语言的人不能以90%的准确率正确地猜出非混淆的Fortran或Python的意图。

考虑以下代码

    int a[10];
    a[0] = 0;
    a[1] = 0;
    a[2] = 0;
    a[3] = 0;
    int i = 0;
    a[i++] = i++;
    a[i++] = i++;
    a[i++] = i++;

由于i++被求值两次,因此输出为 (from vs2005调试器)

    [0] 0   int
    [1] 0   int
    [2] 2   int
    [3] 0   int
    [4] 4   int

现在考虑下面的代码:

    int a[10];
    a[0] = 0;
    a[1] = 0;
    a[2] = 0;
    a[3] = 0;
    int i = 0;
    a[++i] = ++i;
    a[++i] = ++i;
    a[++i] = ++i;

注意,输出是相同的。现在你可能认为++i和i++是一样的。他们不是

    [0] 0   int
    [1] 0   int
    [2] 2   int
    [3] 0   int
    [4] 4   int

最后考虑下面的代码

    int a[10];
    a[0] = 0;
    a[1] = 0;
    a[2] = 0;
    a[3] = 0;
    int i = 0;
    a[++i] = i++;
    a[++i] = i++;
    a[++i] = i++;

现在的输出是:

    [0] 0   int
    [1] 1   int
    [2] 0   int
    [3] 3   int
    [4] 0   int
    [5] 5   int

所以它们是不一样的,两者混合会导致不那么直观的行为。我认为for循环适用于++,但当你在同一行或同一指令上有多个++符号时要小心

我一直在看Douglas Crockford关于这个的视频他对不使用递增和递减的解释是

在过去的其他语言中,它被用来打破数组的界限,并导致各种各样的坏和 它更令人困惑,没有经验的JS开发人员不知道它到底是做什么的。

首先,JavaScript中的数组是动态大小的,因此,如果我说错了,请原谅我,在JavaScript中使用这种方法不可能打破数组的界限并访问不应该访问的数据。

其次,我们是否应该避免那些复杂的东西,当然问题不在于我们有这个工具,而在于有些开发者声称要做JavaScript,但不知道这些操作符是如何工作的?这很简单。Value ++,给我当前的值,在表达式之后加1,++ Value,在给我它之前增加值。

像a ++ + ++ b这样的表达式,只要记住上面的内容,就很容易计算出来。

var a = 1, b = 1, c;
c = a ++ + ++ b;
// c = 1 + 2 = 3; 
// a = 2 (equals two after the expression is finished);
// b = 2;

我想你只需要记住谁需要通读代码,如果你有一个对JS了如指掌的团队,那你就不用担心了。如果不是,那么评论它,以不同的方式写它,等等。做你该做的。我不认为递增和递减本身就不好,或者产生错误,或者产生漏洞,可能只是根据你的读者的不同,可读性更差。

顺便说一句,我认为道格拉斯·克罗克福德是一个传奇,但我认为他引起了很多恐慌,因为他是一个不值得的操作员。

我活着就是为了证明我是错的……

我的观点是在一行中单独使用++和——,如下所示:

i++;
array[i] = foo;

而不是

array[++i] = foo;

在我看来,任何超出这个范围的事情都会让一些程序员感到困惑。For循环是一个例外,因为增量操作符的使用是惯用的,因此总是明确的。

对于不熟悉自增和自减操作符的人来说,它们的“前”和“后”性质容易让人感到困惑;这是它们可能很棘手的一种方式。