jslint工具的一个提示是:

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

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

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

or

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

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


当前回答

在循环中,它是无害的,但在赋值语句中,它会导致意想不到的结果:

var x = 5;
var y = x++; // y is now 5 and x is 6
var z = ++x; // z is now 7 and x is 7

变量和操作符之间的空格也会导致意想不到的结果:

a = b = c = 1; a ++ ; b -- ; c; console.log('a:', a, 'b:', b, 'c:', c)

在闭包中,意外的结果也可能是一个问题:

var foobar = function(i){var count = count || i; return function(){return count++;}}

baz = foobar(1);
baz(); //1
baz(); //2


var alphabeta = function(i){var count = count || i; return function(){return ++count;}}

omega = alphabeta(1);
omega(); //2
omega(); //3

它会自动在换行后插入分号:

var foo = 1, bar = 2, baz = 3, alpha = 4, beta = 5, delta = alpha
++beta; //delta is 4, alpha is 4, beta is 6

增量前/增量后的混淆会产生差一的错误,这很难诊断。幸运的是,它们也是完全不必要的。给变量加1有更好的方法。

参考文献

JSLint帮助:增加和减少操作符

其他回答

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

i++;
array[i] = foo;

而不是

array[++i] = foo;

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

C语言中有这样的历史:

while (*a++ = *b++);

复制一个字符串,也许这就是他所提到的过度欺骗的来源。

总是会有一个问题

++i = i++;

or

i = i++ + ++i;

实际上做的。它在一些语言中有定义,而在其他语言中并不能保证会发生什么。

撇开这些例子不谈,我认为没有什么比使用++进行递增的for循环更习惯的了。在某些情况下,您可以使用foreach循环或while循环来检查不同的条件。但是为了避免使用递增而扭曲代码是荒谬的。

另一个例子,比其他一些简单的递增值返回更简单:

function testIncrement1(x) {
    return x++;
}

function testIncrement2(x) {
    return ++x;
}

function testIncrement3(x) {
    return x += 1;
}

console.log(testIncrement1(0)); // 0
console.log(testIncrement2(0)); // 1
console.log(testIncrement3(0)); // 1

如您所见,如果希望此操作符影响结果,则不应在return语句中使用后递增/递减操作。但是return不会“捕获”自增/自减操作符:

function closureIncrementTest() {
    var x = 0;

    function postIncrementX() {
        return x++;
    }

    var y = postIncrementX();

    console.log(x); // 1
}

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的意图。

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

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

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

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