[javascript] JavaScript에서 증가 (“++”) 및 감소 (“-”) 연산자를 피해야하는 이유는 무엇입니까?

jslint 도구 중 하나 는 다음과 같습니다.

++ 및-
++ (증가) 및-(감소) 연산자는 과도한 까다 로움을 유발하여 잘못된 코드에 기여하는 것으로 알려져 있습니다. 바이러스 및 기타 보안 위협을 가능하게하는 잘못된 아키텍처에 이어 두 번째입니다. 이 연산자의 사용을 금지하는 플러스 플러스 옵션이 있습니다.

나는 PHP 구문 $foo[$bar++]이 쉽게 하나의 오류로 인해 발생할 수 있다는 것을 알고 있지만 a while( a < 10 ) do { /* foo */ a++; }또는 보다 루프를 제어하는 ​​더 좋은 방법을 알 수는 없습니다 for (var i=0; i<10; i++) { /* foo */ }.

++“및 ” --“구문 이없는 유사한 언어가 있거나 다르게 처리하거나, ” ++“및 ” --” 를 피할 수있는 다른 근거가 있기 때문에 jslint가 강조 표시 합니까?



답변

내 견해는 항상 ++를 사용하는 것입니다.

i++;
array[i] = foo;

대신에

array[++i] = foo;

그 이외의 것은 프로그래머에게 혼란을 줄 수 있으며 내 견해로는 가치가 없습니다. 증분 연산자의 사용은 관용적이므로 항상 명확하므로 For 루프는 예외입니다.


답변

나는 그 조언에 솔직히 혼란스러워합니다. 저의 일부는 자바 스크립트 코더에 대한 경험 부족 (인지 또는 실제)과 더 관련이 있는지 궁금합니다.

누군가가 일부 샘플 코드에서 “해킹”하는 방법이 ++와 무고한 실수를 할 수있는 방법을 알 수 있지만 숙련 된 전문가가 왜 피할 수 없는지 알 수 없습니다.


답변

C에는 다음과 같은 일을 한 역사가 있습니다.

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

문자열을 복사하려면 아마도 이것이 언급 한 과도한 속임수의 원천 일 것입니다.

그리고 항상 무엇에 대한 질문이 있습니다

++i = i++;

또는

i = i++ + ++i;

실제로 그렇습니다. 일부 언어로 정의되어 있으며 다른 언어에서는 어떤 일이 일어날 지 보장하지 않습니다.

이러한 예를 제외하고는 ++증가 하는 데 사용하는 for 루프보다 관용적 인 것이 없다고 생각 합니다. 어떤 경우에는 foreach 루프 또는 다른 조건을 확인한 while 루프를 사용하여 벗어날 수 있습니다. 그러나 증분을 사용하지 않고 코드를 왜곡하는 것은 어리 석습니다.


답변

JavaScript The Good Parts를 읽으면 for 루프 에서 Crockford의 i ++ 대체 가 i + = 1 (i = i + 1 아님) 임을 알 수 있습니다 . 그것은 꽤 깨끗하고 읽을 수 있으며 무언가 까다로운 것으로 변형 될 가능성이 적습니다.

크록 포드는 자동 증가를 허용하지하고 자동 감소 만든 옵션 jsLint에 있습니다. 조언을 따를 지 여부를 선택합니다.

내 자신의 개인 규칙은 자동 증가 또는 자동 감소와 결합 된 것을하지 않는 것입니다.

수년간의 C 경험을 통해 간단한 사용으로 버퍼 오버런 (또는 배열 인덱스가 범위를 벗어남)을 얻지 못한다는 것을 배웠습니다. 그러나 같은 문장에서 다른 일을하는 “과도하게 까다로운”관행에 빠지면 버퍼 오버런이 발생한다는 것을 알게되었습니다.

따라서 내 규칙에 대해서는 for 루프 에서 i ++를 증분으로 사용하는 것이 좋습니다.


답변

루프에서는 무해하지만 할당 문에서 예기치 않은 결과가 발생할 수 있습니다.

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을 더하는 더 좋은 방법이 있습니다.

참고 문헌


답변

다음 코드를 고려하십시오

    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 ++은 두 배로 평가되므로 출력은 (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 루프가 ++에서는 괜찮다고 생각하지만 같은 줄이나 동일한 명령어에 여러 ++ 기호가있을 때 조심하십시오.


답변

증가 및 감소 연산자의 “사전”및 “사후”특성은 익숙하지 않은 사용자에게는 혼동을 줄 수 있습니다. 그것이 까다로울 수있는 한 가지 방법입니다.