우리는 학교 출신의 교환원을 많이 알고 있습니다. 덧셈 +
, 곱셈 *
, 뺄셈 -
등과 같은 것들이 있습니다.
이 장에서는 간단한 연산자부터 시작한 다음 학교 산술에서 다루지 않는 JavaScript 관련 측면에 집중할 것입니다.
계속 진행하기 전에 몇 가지 일반적인 용어를 파악해 보겠습니다.
피연산자 – 연산자가 적용되는 것입니다. 예를 들어, 5 * 2
의 곱셈에는 두 개의 피연산자가 있습니다. 왼쪽 피연산자는 5
이고 오른쪽 피연산자는 2
입니다. 때때로 사람들은 이러한 것을 "피연산자" 대신 "인수"라고 부릅니다.
피연산자가 하나만 있으면 연산자는 단항 입니다. 예를 들어, 단항 부정 -
숫자의 부호를 반대로 바꿉니다.
x = 1이라고 하자; x = -x; 경고( x ); // -1, 단항 부정이 적용되었습니다.
피연산자가 두 개인 경우 연산자는 이진 입니다. 동일한 마이너스가 이진 형식으로도 존재합니다.
x = 1, y = 3이라고 가정합니다. 경고(y - x); // 2, 이진 빼기 값 빼기
공식적으로 위의 예에는 동일한 기호를 공유하는 두 가지 다른 연산자가 있습니다. 즉, 부호를 바꾸는 단항 연산자인 부정 연산자와 한 숫자를 다른 숫자에서 빼는 이진 연산자인 빼기 연산자입니다.
다음 수학 연산이 지원됩니다.
덧셈 +
,
빼기 -
,
곱셈 *
,
분할 /
,
나머지 %
,
지수화 **
.
처음 4개는 간단하지만 %
와 **
에 대해서는 몇 가지 단어가 필요합니다.
나머지 연산자 %
겉보기에도 불구하고 백분율과 관련이 없습니다.
a % b
의 결과는 a
를 b
로 나눈 나머지입니다.
예를 들어:
경고( 5 % 2 ); // 1, 5를 2로 나눈 나머지 경고( 8 % 3 ); // 2, 8을 3으로 나눈 나머지 경고( 8 % 4 ); // 0, 8을 4로 나눈 나머지
지수 연산자 a ** b
a
를 b
제곱합니다.
학교 수학에서는 이를 a b 로 씁니다.
예를 들어:
경고( 2 ** 2 ); // 2² = 4 경고( 2 ** 3 ); // 2³ = 8 경고( 2 ** 4 ); // 2⁴ = 16
수학에서와 마찬가지로 지수 연산자는 정수가 아닌 숫자에 대해서도 정의됩니다.
예를 들어, 제곱근은 ½의 지수입니다.
경고( 4 ** (1/2) ); // 2 (1/2의 거듭제곱은 제곱근과 같습니다) 경고( 8 ** (1/3) ); // 2 (1/3의 거듭제곱은 세제곱근과 같습니다)
학교 산수를 뛰어넘는 자바스크립트 연산자의 특징을 만나보세요.
일반적으로 더하기 연산자 +
는 숫자의 합을 계산합니다.
그러나 바이너리 +
문자열에 적용되면 문자열을 병합(연결)합니다.
let s = "내" + "문자열"; 경고; // mystring
피연산자 중 하나라도 문자열이면 다른 피연산자도 문자열로 변환됩니다.
예를 들어:
경고( '1' + 2 ); // "12" 경고( 2 + '1' ); // "21"
첫 번째 피연산자가 문자열인지 두 번째 피연산자인지는 중요하지 않습니다.
더 복잡한 예는 다음과 같습니다.
경고(2 + 2 + '1' ); // "221"이 아닌 "41"
여기에서는 운영자가 차례로 작업합니다. 첫 번째 +
두 숫자의 합을 계산하므로 4
반환하고, 다음 +
는 문자열 1
추가하므로 4 + '1' = '41'
과 같습니다.
경고('1' + 2 + 2); // "14"가 아닌 "122"
여기서 첫 번째 피연산자는 문자열이고, 컴파일러는 다른 두 피연산자도 문자열로 처리합니다. 2
는 '1'
로 연결되므로 '1' + 2 = "12"
및 "12" + 2 = "122"
와 같습니다.
이항 +
는 이러한 방식으로 문자열을 지원하는 유일한 연산자입니다. 다른 산술 연산자는 숫자로만 작동하며 항상 피연산자를 숫자로 변환합니다.
뺄셈과 나눗셈에 대한 데모는 다음과 같습니다.
경고( 6 - '2' ); // 4, '2'를 숫자로 변환합니다. 경고( '6' / '2' ); // 3, 두 피연산자를 모두 숫자로 변환합니다.
더하기 +
위에서 사용한 이진 형식과 단항 형식의 두 가지 형식으로 존재합니다.
단항 더하기, 즉 단일 값에 적용된 더하기 연산자 +
는 숫자에 아무 작업도 수행하지 않습니다. 그러나 피연산자가 숫자가 아닌 경우 단항 더하기는 이를 숫자로 변환합니다.
예를 들어:
// 숫자에는 영향을 주지 않습니다. x = 1이라고 하자; 경고( +x ); // 1 y = -2로 둡니다. 경고( +y ); // -2 // 숫자가 아닌 값을 변환합니다. 경고( +true ); // 1 경고( +"" ); // 0
실제로는 Number(...)
와 동일한 작업을 수행하지만 더 짧습니다.
문자열을 숫자로 변환해야 하는 경우가 자주 발생합니다. 예를 들어 HTML 양식 필드에서 값을 가져오는 경우 일반적으로 문자열입니다. 그것들을 합산하고 싶다면 어떻게 해야 할까요?
바이너리 플러스는 이를 문자열로 추가합니다.
사과 = "2"라고 놔두세요; 오렌지 = "3"으로 둡니다. 경고(사과 + 오렌지); // "23", 이진 더하기는 문자열을 연결합니다.
이를 숫자로 처리하려면 변환한 다음 합산해야 합니다.
사과 = "2"라고 놔두세요; 오렌지 = "3"으로 둡니다. // 두 값 모두 이진 더하기 이전의 숫자로 변환됩니다. 경고( +사과 + +오렌지); // 5 // 더 긴 변형 // 경고( 숫자(사과) + 숫자(오렌지) ); // 5
수학자 입장에서는 플러스의 풍부함이 이상하게 보일 수도 있습니다. 그러나 프로그래머의 관점에서는 특별한 것이 없습니다. 단항 더하기가 먼저 적용되고 문자열을 숫자로 변환한 다음 이진 더하기가 이를 합산합니다.
이진 값 이전의 값에 단항 플러스가 적용되는 이유는 무엇입니까? 앞으로 살펴보겠지만 이는 우선 순위가 더 높기 때문입니다.
표현식에 연산자가 두 개 이상 있는 경우 실행 순서는 우선 순위 , 즉 연산자의 기본 우선 순위에 따라 정의됩니다.
학교에서 우리는 1 + 2 * 2
표현식의 곱셈이 덧셈보다 먼저 계산되어야 한다는 것을 알고 있습니다. 그게 바로 우선순위죠. 곱셈이 덧셈보다 우선순위가 높다고 합니다.
괄호는 우선순위를 무시하므로 기본 순서가 만족스럽지 않으면 괄호를 사용하여 변경할 수 있습니다. 예를 들어 (1 + 2) * 2
라고 씁니다.
JavaScript에는 많은 연산자가 있습니다. 모든 연산자에는 해당 우선순위 번호가 있습니다. 숫자가 큰 것이 먼저 실행됩니다. 우선순위가 동일한 경우 실행 순서는 왼쪽에서 오른쪽입니다.
다음은 우선순위 테이블에서 발췌한 내용입니다(기억할 필요는 없지만 단항 연산자가 해당 이진 연산자보다 높다는 점에 유의하세요).
상위 | 이름 | 징후 |
---|---|---|
… | … | … |
14 | 단항 플러스 | + |
14 | 단항 부정 | - |
13 | 지수화 | ** |
12 | 곱셈 | * |
12 | 분할 | / |
11 | 덧셈 | + |
11 | 빼기 | - |
… | … | … |
2 | 과제 | = |
… | … | … |
보시다시피, "단항 플러스"는 "덧셈"(이진 플러스)의 11
보다 높은 14
의 우선순위를 갖습니다. 이것이 바로 "+apples + +oranges"
표현식에서 단항 플러스가 더하기 전에 작동하는 이유입니다.
=
할당도 연산자라는 점에 유의하세요. 이는 매우 낮은 우선순위인 2
로 우선순위 테이블에 나열됩니다.
그렇기 때문에 x = 2 * 2 + 1
과 같은 변수를 할당하면 계산이 먼저 수행된 다음 =
가 평가되어 결과가 x
에 저장됩니다.
x = 2 * 2 + 1이라고 하자; 경고( x ); // 5
=
가 "마법의" 언어 구조가 아니라 연산자라는 사실은 흥미로운 의미를 갖습니다.
JavaScript의 모든 연산자는 값을 반환합니다. +
및 -
의 경우에는 분명하지만 =
의 경우에도 마찬가지입니다.
x = value
호출은 value
x
에 쓴 다음 반환합니다 .
다음은 더 복잡한 표현식의 일부로 할당을 사용하는 데모입니다.
a = 1이라고 하자; b = 2라고 하자; c = 3 - (a = b + 1)이라고 하자; 경고( a ); // 3 경고(c); // 0
위의 예에서 식 (a = b + 1)
의 결과는 a
에 할당된 값(즉 3
)입니다. 그런 다음 추가 평가에 사용됩니다.
재미있는 코드죠? 때로는 JavaScript 라이브러리에서 볼 수 있기 때문에 이것이 어떻게 작동하는지 이해해야 합니다.
하지만 그런 코드는 작성하지 마세요. 이러한 트릭은 확실히 코드를 더 명확하거나 읽기 쉽게 만들지 않습니다.
또 다른 흥미로운 기능은 할당을 연결하는 기능입니다.
a, b, c를 보자; a = b = c = 2 + 2; 경고( a ); // 4 경고(b); // 4 경고(c); // 4
연결된 할당은 오른쪽에서 왼쪽으로 평가됩니다. 먼저 가장 오른쪽 표현식 2 + 2
평가된 후 왼쪽 변수 c
, b
및 a
에 할당됩니다. 결국 모든 변수는 단일 값을 공유합니다.
다시 한 번 말하지만, 가독성을 위해 이러한 코드를 몇 줄로 나누는 것이 좋습니다.
c = 2 + 2; b = c; a = c;
특히 코드를 빠르게 눈으로 스캔할 때 읽기가 더 쉽습니다.
변수에 연산자를 적용하고 새 결과를 동일한 변수에 저장해야 하는 경우가 종종 있습니다.
예를 들어:
n = 2라고 하자; n = n + 5; n = n * 2;
이 표기법은 +=
및 *=
연산자를 사용하여 단축할 수 있습니다.
n = 2라고 하자; n += 5; // 이제 n = 7 (n = n + 5와 동일) n *= 2; // 이제 n = 14 (n = n * 2와 동일) 경고(n); // 14
모든 산술 및 비트 연산자에는 짧은 "수정 및 할당" 연산자가 있습니다: /=
, -=
등.
이러한 연산자는 일반 할당과 동일한 우선순위를 가지므로 대부분의 다른 계산 후에 실행됩니다.
n = 2라고 하자; n *= 3 + 5; // 오른쪽 부분이 먼저 평가됩니다. n과 동일 *= 8 경고(n); // 16
숫자를 1씩 늘리거나 줄이는 것은 가장 일반적인 수치 연산 중 하나입니다.
따라서 이를 위한 특수 연산자가 있습니다.
Increment ++
는 변수를 1씩 증가시킵니다.
카운터 = 2로 설정합니다. 카운터++; // counter = counter + 1과 동일하게 작동하지만 더 짧습니다. 경고(카운터); // 3
감소 --
변수를 1씩 감소시킵니다.
카운터 = 2로 설정; 계수기--; // counter = counter - 1과 동일하게 작동하지만 더 짧습니다. 경고(카운터); // 1
중요한:
증가/감소는 변수에만 적용할 수 있습니다. 5++
와 같은 값에 사용하려고 하면 오류가 발생합니다.
++
및 --
연산자는 변수 앞이나 뒤에 위치할 수 있습니다.
연산자가 변수 뒤에 오면 "접미사 형식"입니다: counter++
.
"접두사 형식"은 연산자가 변수 앞에 오는 경우입니다: ++counter
.
이 두 명령문은 모두 동일한 작업을 수행합니다. 즉, counter
1
만큼 증가시킵니다.
차이점이 있나요? 예, 하지만 ++/--
반환 값을 사용하는 경우에만 볼 수 있습니다.
명확히합시다. 우리가 알고 있듯이 모든 연산자는 값을 반환합니다. 증가/감소도 예외는 아닙니다. 접두사 형식은 새 값을 반환하는 반면, 후위 형식은 이전 값(증가/감소 전)을 반환합니다.
차이점을 확인하려면 다음 예를 참조하세요.
카운터 = 1로 설정; a = ++카운터라고 하자; // (*) 경고(a); // 2
(*)
줄에서 ++counter
형식의 접두사는 counter
증가시키고 새 값인 2
반환합니다. 따라서 alert
2
표시됩니다.
이제 접미사 형식을 사용해 보겠습니다.
카운터 = 1로 설정; a = 카운터++라고 하자; // (*) ++counter를 counter++로 변경했습니다. 경고(a); // 1
(*)
행에서 후위 형식 counter++
도 counter
증가시키지만 이전 값(증가 전)을 반환합니다. 따라서 alert
1
표시됩니다.
요약하자면:
증가/감소 결과를 사용하지 않는 경우 어떤 형식을 사용하든 차이가 없습니다.
카운터 = 0으로 둡니다. 카운터++; ++카운터; 경고(카운터); // 2, 위의 줄도 마찬가지입니다.
값을 늘리고 연산자의 결과를 즉시 사용하려면 접두사 형식이 필요합니다.
카운터 = 0으로 둡니다. 경고( ++카운터 ); // 1
값을 증가시키고 싶지만 이전 값을 사용하려면 후위 형식이 필요합니다.
카운터 = 0으로 둡니다. 경고(카운터++); // 0
다른 연산자 간의 증가/감소
++/--
연산자는 표현식 내에서도 사용할 수 있습니다. 이들 연산의 우선순위는 대부분의 다른 산술 연산보다 높습니다.
예를 들어:
카운터 = 1로 설정; 경고( 2 * ++카운터 ); // 4
비교:
카운터 = 1로 설정; 경고( 2 * 카운터++ ); // 2, counter++가 "이전" 값을 반환하기 때문입니다.
기술적으로는 문제가 없지만 이러한 표기법은 일반적으로 코드를 읽기 어렵게 만듭니다. 한 줄이 여러 가지 작업을 수행하지만 좋지는 않습니다.
코드를 읽는 동안 빠른 "수직" 눈 스캔은 counter++
와 같은 항목을 쉽게 놓칠 수 있으며 변수가 증가했는지 명확하지 않습니다.
우리는 “한 줄 – 한 행동” 스타일을 권장합니다:
카운터 = 1로 설정; 경고( 2 * 카운터 ); 카운터++;
비트 연산자는 인수를 32비트 정수로 처리하고 이진 표현 수준에서 작동합니다.
이러한 연산자는 JavaScript에만 국한되지 않습니다. 대부분의 프로그래밍 언어에서 지원됩니다.
연산자 목록:
그리고 ( &
)
또는 ( |
)
XOR( ^
)
아님 ( ~
)
왼쪽 시프트( <<
)
오른쪽 시프트( >>
)
0으로 채우기 오른쪽 시프트( >>>
)
이러한 연산자는 가장 낮은(비트 단위) 수준의 숫자를 조작해야 할 때 거의 사용되지 않습니다. 웹 개발에서는 이러한 연산자를 거의 사용하지 않기 때문에 조만간 이러한 연산자가 필요하지 않을 것입니다. 그러나 암호화와 같은 일부 특수 영역에서는 유용합니다. 필요할 때 MDN의 Bitwise Operators 장을 읽어보세요.
쉼표 연산자 ,
가장 희귀하고 특이한 연산자 중 하나입니다. 때로는 더 짧은 코드를 작성하는 데 사용되므로 무슨 일이 일어나고 있는지 이해하려면 이를 알아야 합니다.
쉼표 연산자를 사용하면 여러 표현식을 쉼표 ,
로 나누어 평가할 수 있습니다. 각각은 평가되지만 마지막 결과만 반환됩니다.
예를 들어:
a = (1 + 2, 3 + 4)라고 하자; 경고( a ); // 7 (3 + 4의 결과)
여기에서는 첫 번째 표현식 1 + 2
가 평가되고 그 결과가 버려집니다. 그런 다음 3 + 4
평가되어 결과로 반환됩니다.
쉼표의 우선순위가 매우 낮습니다.
쉼표 연산자는 =
보다 우선순위가 매우 낮으므로 위 예에서는 괄호가 중요합니다.
그것들이 없으면 a = 1 + 2, 3 + 4
+
먼저 평가하고 숫자를 a = 3, 7
로 합산한 다음 할당 연산자 =
가 a = 3
할당하고 나머지는 무시됩니다. (a = 1 + 2), 3 + 4
와 같습니다.
마지막 표현식을 제외한 모든 것을 버리는 연산자가 필요한 이유는 무엇입니까?
때때로 사람들은 여러 작업을 한 줄에 넣기 위해 더 복잡한 구조에서 이를 사용합니다.
예를 들어:
// 한 줄에 세 가지 작업 for (a = 1, b = 3, c = a * b; a < 10; a++) { ... }
이러한 트릭은 많은 JavaScript 프레임워크에서 사용됩니다. 그것이 우리가 그들을 언급하는 이유입니다. 그러나 일반적으로 코드 가독성이 향상되지 않으므로 사용하기 전에 잘 생각해야 합니다.
중요도: 5
아래 코드 뒤에 나오는 모든 변수 a
, b
, c
및 d
의 최종 값은 무엇입니까?
a = 1, b = 1이라고 가정합니다. c = ++a로 두세요; // ? d = b++라고 하자; // ?
대답은 다음과 같습니다.
a = 2
b = 2
c = 2
d = 1
a = 1, b = 1이라고 가정합니다. 경고( ++a ); // 2, 접두사 형식은 새 값을 반환합니다. 경고(b++); // 1, 후위 형식은 이전 값을 반환합니다. 경고( a ); // 2, 한 번 증가 경고(b); // 2, 한 번 증가
중요도: 3
아래 코드 뒤의 a
와 x
의 값은 무엇입니까?
a = 2라고 하자; x = 1 + (a *= 2)라고 하자;
대답은 다음과 같습니다.
a = 4
(2를 곱함)
x = 5
(1 + 4로 계산됨)
중요도: 5
이 표현의 결과는 무엇입니까?
"" + 1 + 0 "" - 1 + 0 참 + 거짓 6 / "3" "2" * "3" 4 + 5 + "픽셀" "$" + 4 + 5 "4" - 2 "4px" - 2 " -9 " + 5 " -9 " - 5 널 + 1 정의되지 않음 + 1 " t n" - 2
잘 생각하고 적어본 다음 답과 비교해 보세요.
"" + 1 + 0 = "10" // (1) "" - 1 + 0 = -1 // (2) 참 + 거짓 = 1 6 / "3" = 2 "2" * "3" = 6 4 + 5 + "px" = "9px" "$" + 4 + 5 = "$45" "4" - 2 = 2 "4px" - 2 = NaN " -9 " + 5 = " -9 5" // (3) " -9 " - 5 = -14 // (4) 널 + 1 = 1 // (5) 정의되지 않음 + 1 = NaN // (6) " t n" - 2 = -2 // (7)
문자열 "" + 1
더하면 1
문자열로 변환됩니다: "" + 1 = "1"
, 그런 다음 "1" + 0
되며 동일한 규칙이 적용됩니다.
빼기 -
(대부분의 수학 연산과 마찬가지로) 숫자로만 작동하며 빈 문자열 ""
을 0
으로 변환합니다.
문자열을 추가하면 문자열에 숫자 5
가 추가됩니다.
빼기는 항상 숫자로 변환되므로 " -9 "
는 숫자 -9
가 됩니다(주위의 공백은 무시함).
숫자 변환 후 null
0
됩니다.
undefined
숫자 변환 후 NaN
이 됩니다.
문자열이 숫자로 변환될 때 공백 문자는 문자열 시작과 끝에서 잘립니다. 여기서 전체 문자열은 t
, n
과 같은 공백 문자와 그 사이의 "일반" 공백으로 구성됩니다. 따라서 빈 문자열과 유사하게 0
이 됩니다.
중요도: 5
다음은 사용자에게 두 개의 숫자를 요청하고 그 합계를 표시하는 코드입니다.
제대로 작동하지 않습니다. 아래 예의 출력은 12
입니다(기본 프롬프트 값의 경우).
왜? 문제를 해결하세요. 결과는 3
이어야 합니다.
let a = 프롬프트("첫 번째 숫자?", 1); let b = 프롬프트("두 번째 숫자는요?", 2); 경고(a + b); // 12
그 이유는 프롬프트가 사용자 입력을 문자열로 반환하기 때문입니다.
따라서 변수의 값은 각각 "1"
과 "2"
입니다.
a = "1"이라고 하자; // 프롬프트("첫번째 숫자는요?", 1); b = "2"라고 하자; // 프롬프트("두 번째 숫자는요?", 2); 경고(a + b); // 12
우리가 해야 할 일은 +
앞에 문자열을 숫자로 변환하는 것입니다. 예를 들어 Number()
사용하거나 앞에 +
를 추가합니다.
예를 들어 prompt
바로 앞에 다음이 있습니다.
let a = +prompt("첫 번째 숫자?", 1); let b = +prompt("두 번째 숫자는요?", 2); 경고(a + b); // 3
또는 alert
에서 :
let a = 프롬프트("첫 번째 숫자?", 1); let b = 프롬프트("두 번째 숫자는요?", 2); 경고(+a + +b); // 3
최신 코드에서는 단항 및 이진 +
모두 사용합니다. 재미있어 보이지 않나요?