JavaScript에서 증분("+") 및 감소("--") 연산자를 사용하지 않는 이유는 무엇입니까?
도구의 힌트 중 하나는 다음과 같습니다.
++
★★★★★★★★★★★★★★★★★」--
++
및 (기호) »--
(평가) 운영자는 과도한 속임수를 조장함으로써 악성코드의 원인이 되는 것으로 알려져 있습니다.바이러스 및 기타 보안 위협에 대한 대응은 아키텍처의 장애에 버금가는 것입니다.이러한 연산자의 사용을 금지하는 플러스 옵션이 있습니다.
는 PHP로 되어 있는 으로 알고 .$foo[$bar++]
가 발생하기 , 하는 방법은 a1의 에러보다 더 방법을 수 .
while( a < 10 ) do { /* foo */ a++; }
또는
for (var i=0; i<10; i++) { /* foo */ }
jslint
'아까운 언어'가 해 줍니다.++
및 " " " "--
다루거나, 다른 로 '어울리다'를피할 수 이 있을까요?++
및 " " " "--
가가고고고고고고?
제 견해는 다음과 같이 항상 ++와 --를 한 줄에 단독으로 사용하는 것입니다.
i++;
array[i] = foo;
대신
array[++i] = foo;
그 이상의 것은 일부 프로그래머에게는 혼란스러울 수 있으며, 제 생각에는 그럴 가치가 없습니다.루프는 예외입니다.증분 연산자의 사용은 관용적이기 때문에 항상 명확합니다.
C에는 다음과 같은 일을 한 전력이 있습니다.
while (*a++ = *b++);
아마도 이것이 그가 언급하고 있는 과도한 속임수의 근원일 것이다.
그리고 항상 의문이 생기기 마련이죠.
++i = i++;
또는
i = i++ + ++i;
사실 그렇긴 해요.어떤 언어에서는 정의되어 있고 어떤 언어에서는 어떤 일이 일어날지 장담할 수 없습니다.
차치하고 것 요.++
다른 수 있는 가 있습니다.경우에 따라서는 foreach 루프 또는 다른 상태를 체크한 while 루프에서 벗어날 수 있습니다.그러나 코드를 왜곡하여 증가되는 사용을 피하는 것은 말도 안 된다.
JavaScript The Good Parts를 읽으면 For 루프에서 Crockford의 i++ 대체품이 i+=1(i=i+1이 아님)임을 알 수 있습니다.그것은 꽤 깔끔하고 읽기 쉬우며, "이상한" 것으로 변형될 가능성이 낮다.
Crockford는 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 디버거에서) 출력의 2배로 평가되기 때문에
[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
즉, 이 두 가지를 혼합하면 직관적인 동작이 되지 않습니다.루프의 경우 ++는 괜찮다고 생각하지만, 같은 줄이나 같은 명령어에 ++ 기호가 여러 개 있을 때는 주의하십시오.
증가 및 감소 연산자의 "사전"과 "사후" 특성은 익숙하지 않은 사람들에게 혼란을 줄 수 있습니다. 이것이 까다로울 수 있는 한 가지 방법입니다.
내 견해로는, "명시적인 것이 암묵적인 것보다 항상 낫다."왜냐하면 어느 시점에서 이 증분 문장과 혼동될 수 있기 때문입니다.y+ = x++ + ++y
훌륭한 프로그래머는 항상 자신의 코드를 더 읽기 쉽게 만듭니다.
더글라스 크록포드의 비디오를 보고 있는데 증감하지 않는 것에 대한 그의 설명은
- 이것은 배열의 경계를 허물고 모든 나쁜 예절을 야기하기 위해 과거 다른 언어에서 사용되었습니다.
- 더 혼란스럽고 경험이 부족한 JS 개발자들은 JS의 기능을 정확히 알지 못합니다.
우선 JavaScript의 어레이는 동적으로 사이즈가 정해져 있기 때문에 틀렸다면 양해 바랍니다.JavaScript에서는 이 방법으로 액세스해서는 안 되는 어레이의 경계를 깨고 데이터에 액세스 할 수 없습니다.
둘째, 복잡한 것은 피해야 합니다.문제는 확실히 이 설비를 가지고 있는 것이 아니라 자바스크립트를 한다고 주장하지만 이들 오퍼레이터가 어떻게 동작하는지 모르는 개발자가 있다는 것입니다.간단합니다. 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 반환값을 사용하지 않는 경우(임시 없음)
- 반환값 사용 시 i++(파이프라인이 정지하지 않음)
나는 크록포드 씨의 팬이지만, 이 경우에는 동의하지 않을 수 없다. ++i
가 ""보다 .i+=1
분명 분명할 거예요
또 다른 예로는 다른 예보다 단순하고 단순한 값의 반환을 들 수 있습니다.
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 스테이트먼트에서는 post-increment/decrement를 사용하지 마십시오.그러나 수익률은 증가/감소 후 연산자를 "잡지" 못합니다.
function closureIncrementTest() {
var x = 0;
function postIncrementX() {
return x++;
}
var y = postIncrementX();
console.log(x); // 1
}
프로그래머는 사용하는 언어에 유능해야 하고, 명확하게 사용하고, 잘 사용해야 한다고 생각합니다.나는 그들이 사용하는 언어를 인위적으로 무력화시켜서는 안 된다고 생각한다.나는 경험으로 말한다.나는 말 그대로 코볼 가게 옆집에서 일한 적이 있다. 그들은 '너무 복잡해서' ELSE를 사용하지 않았다.압수르담의 환원
제 경험상, ++i 또는 i++는 오퍼레이터의 동작을 처음 배울 때 이외에는 혼란을 일으킨 적이 없습니다.이것은 가장 기본적인 루프와 오퍼레이터를 사용할 수 있는 언어로 교육된 고등학교 또는 대학 코스에서 학습되는 루프에 필수적입니다.저는 개인적으로 a++가 다른 줄에 있는 것보다 아래 내용을 더 잘 보고 읽을 수 있는 것을 발견합니다.
while ( a < 10 ){
array[a++] = val
}
결국 이것은 스타일 선호도이지 그 이상의 것이 아닙니다.더 중요한 것은 코드로 이것을 할 때 일관성을 유지하는 것입니다.그러면 같은 코드로 작업하고 있는 다른 사람이 같은 기능을 다른 방법으로 처리할 필요가 없어집니다.
또한 Crockford는 i-=1을 사용하는 것 같습니다만, --i나 i보다 읽기 어렵습니다.
기존 답변 중 일부에서 언급했듯이(불쾌하게도 코멘트를 할 수 없음), 문제는 x+++x가 (증가 전과 후의) 다른 값으로 평가된다는 것입니다.이것은 명확하지 않고 그 값이 사용되는 경우 매우 혼란스러울 수 있습니다.cdmckay는 증분 연산자를 사용할 수 있도록 매우 현명하게 제안하지만 반환된 값이 자체 라인에서 사용되지 않는 방식으로만 제안합니다.또한 for 루프에 표준 용도를 포함합니다(단, 반환값이 사용되지 않는 세 번째 문에만 해당).다른 예가 생각나지 않는다.저도 '번트'를 한 적이 있기 때문에 다른 언어에도 같은 가이드라인을 추천합니다.
나는 이러한 과도한 엄격함은 많은 JS 프로그래머들이 경험이 부족하기 때문이라는 주장에 동의하지 않는다.이것은 "매우 똑똑한" 프로그래머들의 전형적인 글쓰기이며, 저는 이것이 좀 더 전통적인 언어들과 그러한 언어들에 대한 배경 지식을 가진 JS 개발자들에게 훨씬 더 흔하다고 확신합니다.
저의 2가지 요점은 두 가지 경우 피해야 한다는 것입니다.
1) 여러 행에서 사용되는 변수가 있는 경우 해당 변수를 사용하는 첫 번째 문(또는 마지막 문 또는 중간 문)에서 변수를 증가/감소하는 경우:
// It's Java, but applies to Js too
vi = list.get ( ++i );
vi1 = list.get ( i + 1 )
out.println ( "Processing values: " + vi + ", " + vi1 )
if ( i < list.size () - 1 ) ...
이러한 예에서는 변수가 자동으로 증가/감소되는 것을 놓치거나 첫 번째 문을 삭제할 수도 있습니다.즉, 매우 짧은 블록 또는 두 개의 닫힘 문장에서 블럭에 변수가 나타나는 경우에만 사용하십시오.
2) 같은 문장에 ++와 --가 여러 개 있는 경우.다음과 같은 경우 어떤 일이 일어나는지 기억하는 것은 매우 어렵습니다.
result = ( ++x - --x ) * x++;
시험이나 프로페셔널 테스트에서는 위와 같은 예에 대해 질문합니다.실제로 그 중 하나에 대한 문서를 찾다가 우연히 이 질문을 발견했습니다만, 실생활에서는 코드 한 줄에 대해 그렇게 많이 생각할 필요는 없습니다.
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은 특히 ++와 --를 가진 절차 언어보다 버그 자석이 덜한가요? 저는 증거가 없습니다.
저는 Fortran과 Python은 C에 능통한 사람을 만나본 적이 없기 때문에 C와 같다고 주장합니다만, 90%정확하게 Fortran이나 Python의 의도를 정확하게 추측할 수 없습니다.
연산자는 프리픽스와 서픽스로 사용할 때 의미가 다르므로 버그를 찾기 어려울 수 있습니다.다음 예에서는 bubbleSort를 사용합니다.
function bubbleSort(array) {
if(array.length === 1) return array;
let end = array.length - 2;
do {
for (let i = 0; i < array.length; i += 1) {
if (array[i] > array[i + 1]) {
swap(array, i, i + 1);
}
}
} while (end--);
}
bubbleSort([6,5]);
프로그램을 실행하는 과정에서 두 항목 값이 정렬 함수에 전달된다고 가정해 보겠습니다.이치노할 수 있다,에서는, 「」, 「」 「 」 「 」end
는 false이며 변수를 감소시키기 전에 루프를 종료합니다.
, 그럼 다음 서 ''를 해 보세요.--
기호는 접미사가 아닌 접두사로 사용됩니다.루프에 .
function bubbleSort(array) {
if(array.length === 1) return array;
let end = array.length - 2;
do {
for (let i = 0; i < array.length; i += 1) {
if (array[i] > array[i + 1]) {
swap(array, i, i + 1);
}
}
} while (--end);
}
bubbleSort([6,5]);
여기서 while 조건에 도달하면 체크하기 전에 종료값이 감소합니다.이것은 Javascript에서 -1을 반환합니다.이것은 truthy 값입니다.
어떻게 사용하는지에 대해서는 강한 의견은 없지만, 부주의하게 사용하면 진짜 버그를 일으킬 수 있다는 것을 보여주고 싶을 뿐입니다.
++의 인수는 ++가 TypeError의 원인이 되는 문자열에는 적용되지 않는다는 것입니다.이것은 거의 항상 바람직합니다.
언급URL : https://stackoverflow.com/questions/971312/why-avoid-increment-and-decrement-operators-in-javascript
'programing' 카테고리의 다른 글
MySQL 삽입 위치...값 및 선택 (0) | 2022.09.12 |
---|---|
왜 String이 없어요?Java에서는 비어있습니까? (0) | 2022.09.12 |
PyPy가 6.3배 빠른데 왜 PyPy over CPython을 사용하면 안 되나요? (0) | 2022.09.12 |
왜 우리는 최종적으로 블록을 사용하는가? (0) | 2022.09.12 |
MariaDB/MySQL을 사용하여 Peeee에서 FLOAT 열 정밀도 지정 (0) | 2022.09.12 |