[Deep Dive] 7장~8장
연산자(operator, 演算) : 수나 식을 일정 규칙으로 계산하는 것
피연산자(operand): 연산의 대상, 값으로 평가될 수 있는 표현식
연산자 → 피연산자를 연산하여 새로운 값을 만듬
피연산자 → 이 연산의 대상이 되어야 하므로 값으로 평가할 수 있어야 함
자바스크립트에서 제공하는 다양한 연산자에는 산술, 할당, 비교, 논리, 타입, 지수 연산 등이 있다.
7.1 산술연산자
// 이항 산술 연산자 : 피연산자 2개
// + - * / %
console.log("--이항--");
// 덧셈
console.log(1 + 5);
// 뺄셈
console.log(6 - 7);
// 곱셈
console.log(2 * 2);
// 나눗셈
console.log(5 / 2);
// 나머지
console.log(7 % 3);
// 거듭제곱
console.log(2 ** 3);
// 사칙연산의 우선순위
console.log(2 + 3 * 2);
console.log((2 + 3) * 2);
// 단항 산술 연산자 : 피연산자 1개
console.log("--단항--");
let num = 1;
console.log(num);
num++;
console.log(num);
num--;
console.log(num);
// 증가/감소 연산자의 위치 주의
// postfix increment operator 선할당 후증가
console.log("--postfix increment--");
let su = 5, result;
result = su++;
console.log("result의 값: ", result, " su의 값: ", su);
console.log("--prefix increment --");
result = ++su;
console.log("result의 값: ", result, " su의 값: ", su);
console.log("--postfix decrement--");
result = su--;
console.log("result의 값: ", result, " su의 값: ", su);
console.log("--prefix decrement--");
result = --su;
console.log("result의 값: ", result, " su의 값: ", su);
// + 단항 연산자는 음수를 양수로 반전하지도 않고 아무 효과 없음
// - 단항 연산자는 양수 -> 음수, 음수 -> 양수 반전 값을 반환
// + 단항 연산자 -> 숫자 타입이 아닌 피연산자에 사용시 숫자 타입으로 리턴
// 피연산자를 변경하는 것은 아니고, 단순히 변환한 값을 생성해 반환(부수 효과 없음)
// 부수 효과 없다는 거는 기존 값을 변경하는 것은 아니라는 뜻
console.log("-- + --");
console.log("-- + string number --");
let b = "1";
console.log(+b);
// 부수 효과 없음
console.log(b);
console.log(typeof b);
// 불린형도 숫자로 타입 변환
console.log("-- + boolean --");
let c = false;
console.log(+c);
console.log(c);
// 문자열은 변환 x -> NaN 반환
console.log("-- + string --");
let d = "Hello";
console.log(+d);
console.log(d);
// 피연산자 중 1개 이상이 문자열인 경우 문자열 연결 연산자로 동작
1+2
// 3
'1'+2
// '12'
1+'2'
// '12'
1 + true
// 2, true는 1로 타입 변환
1 + false
// 1, false는 0으로 타입 변환
1 + null
// 1, null은 0으로 타입 변환
+undefined
// NaN, undefined는 숫자로 타입 변환 안됨
위 예제에서 보면, 의도와 상관없이 자바스크립트 엔진에 의해 암묵적 타입 변환이 이뤄짐
→ 암묵적 타입 변환(implicit coercion) 또는 타입 강제 변환(type coercion)이라 함
→ 관련 자세한 내용은 9장 참고
7.2 할당 연산자
// 할당 연산자(Assignment operator)
// +=,*=, -=, /=, %=
// 문자열 연결도 가능
let str = "My name is ";
// str = str + 'Seoin';
str += "Seoin";
console.log(str);
할당문은 변수에 값을 할당 + 할당문은 표현식 ㅇ
따라서 할당된 값으로 평가된다. → 다른 변수에 할당할 수 있기 때문에 여러 변수에 동일한 값을 연쇄 할당할 수도 있음
// 할당문은 표현식 -> 할당된 값으로 평가됨
// 표현식 == 값으로 평가됨
// 할당문을 다른 변수에 할당 가능
// 연쇄할당 가능
var a1, b1, c1;
a1 = b1 = c1 = 0;
console.log(a1, b1, c1);
** 표현식인 문과 표현식이 아닌 문의 차이
표현식인 문 → 변수에 할당 가능(값으로 평가 ㅇ)
표현식이 아닌 문 → 변수 할당 시 에러(평가 x)
7.3 비교 연산자
좌항과 우항 비교해 결과를 불린형으로 반환
동등 비교(loose equality), 일치 비교(strict equality)
== : 동등 비교, 값 암묵적 타입 변환으로 타입을 일치시킨 후 값 비교
=== : 일치 비교, 타입 타입도 같고 값도 같은 경우에 한해 true 반환(암묵적 타입 변환 없음)
→ 동등 비교 연산자는 결과 예측이 어렵기 때문에 일치 비교를 권장
5 == 5
true
5 == '5'
true
5 === '5'
false
주의 할 점
NaN → 자신과 일치하지 않는 유일한 값
NaN === NaN;
// false
→ 숫자가 NaN인지 알아보려면 빌트인 함수인 isNaN을 사용
0은 양의 0과 음의 0이 있음
0 === -0;
// true
0 == -0;
// true
** Object.is 메서드 → ES6 도입, 보통 일치 비교 연산자(===)와 동일하게 동작
다른 점은
-0 === +0; // → true
Object.is(-0, +0); // → false
NaN === NaN; // → false
Object.is(NaN, NaN); // → true
이외 대소 관계 비교 연산자가 있는데 다 아는 > < ≥ ≤ 으로 불린 값을 반환함
5 > 0; → true
7.4 삼항 조건 연산자
조건식 ? 조건식 true일 때 반환할 값 : 조건식이 false일 때 반환할 값
// 삼항
console.log("--삼항 --");
let three = 10;
let re = three % 2 ? "홀수" : "짝수";
console.log(re);
if..else와 비슷하지만, 값으로 사용할 수 있다는 점에서 if else와 구별됨
값으로 평가할 수 있는 표현식이기 때문에 값처럼 사용가능
7.5 논리 연산자(logical operator)
|| : OR
&& : AND
! : NOT
자바스크립트 관점의 and 연산(&&)
왼쪽 것이 false로 판별되면 false를 반환
왼쪽 것이 true로 판별되면 오른쪽 값을 반환(왼쪽 것이 판별된 후엔 결국 오른쪽 값이 결과 값이 됨)
or 연산 (||)
왼쪽 것이 true로 판별되면 왼쪽 값을 반환
왼쪽 것이 false로 판별되면 오른쪽 값을 반환
// 논리회로에서 true == 1, false == 0
// 논리회로 관점의 and 연산
// and(&&): 둘 다 1일 때 1
// &: ampersand
// 1 && 1 == 1
// 0 && 1 == 0
// 1 && 0 == 0
// 0 && 0 == 0
var resultAnd = x > 0 && x < 10;
console.log(resultAnd); // true
// short-circuit evaluation, lazy evaluation
// 왼쪽의 값으로 논리값 결과가 결정되면 오른쪽의 값은 판별하지 않음
// 자바스크립트 관점의 and(&&) 연산
// 논리연산할 때 피연산자가 부울 값일 필요는 없음
// 왼쪽 것이 false로 판별되면 왼쪽 값을를 반환
// false && true == false
// false && false == false
var resultAndStr1 = "" && "b"; // resultStr3의 값은 ''
// 왼쪽 것이 true로 판별되면 오른쪽 값을 반환
// true && true == true
// true && false == false
var resultAndBool = true && true; // resultAndBool == true
var resultAndStr2 = true && "a"; // resultAndStr2 == 'a'
var resultAndStr3 = "a" && "b"; // resultAndStr3 == 'b'
// 논리회로 관점에서 or 연산
// or(||): 둘 중에 하나라도 1이면 1
// |: pipe
// 1 || 1 == 1
// 0 || 1 == 1
// 1 || 0 == 1
// 0 || 0 == 0
var resultOr = x > 0 || x < 10;
console.log(resultOr); // true
// 자바스크립트 관점의 or(||) 연산
// 왼쪽 것이 true로 판별되면 왼쪽 값을를 반환
// true || true == true
// true || false == true
var resultOrBool1 = true && true; // resultOrBool == true
var resultOrBool2 = true && "a"; // resultOrBool2 == true
var resultOrStr1 = "a" && "b"; // resultOrStr1 == 'a'
// 왼쪽 것이 false로 판별되면 오른쪽 값을 반환
// false || true == true
// false || false == false
var resultAndStr2 = "" && "b"; // resultAndStr2 == 'b'
// NOT(!) 연산
// 판별되다, 평가되다 --> be evaluated
// 연산의 대상이 true로 판별되면 false를 반환
// 연산의 대상이 false로 판별되면 true로 반환
console.log(!true); // false (true의 반대 false)
console.log(!('')); // true (false의 반대 true)
console.log(!('a')); // false(true의 반대 false)
// 어떤 값을 boolean 값으로 변환할 때 !! 느낌표 두개를 사용
var b = "one";
!! b // true
// !!는 "one"을 불린 값으로 변환 실행함.
// !!는 어떤 값을 boolean 값으로 변환할 때 사용한다.
7.6 쉼표 연산자
console.log("--postfix increment--");
let su = 5, result;
// 왼쪽 피연산자부터 차례대로 피연산자 평가, 마지막 피연산자의 평가가 끝나면
// 마지막 피연산자의 평가 결과 반환
7.7 그룹 연산자
// 사칙연산의 우선순위
console.log(2 + 3 * 2);
console.log((2 + 3) * 2);
// 소괄호() -> 연산자 우선순위를 조절할 수 있는 그룹 연산자
7.8 typeof 연산자
내가 지금 사용하는 값이 어떤 자료형인지 확인 할 수 있는 typeof
typeof 연산자 뒤에 값을 적으면 그 값을 평가해서 문자열로 되돌려줌
// number
typeof NaN
// boolean
typeof true
// undefined
typeof undefined
// symbol
typeof Symbol()
// object
typeof null
typeof []
typeof {}
typeof new Date()
typeof /test/gi
- typeof null 이 object로 반환되는 것은 자바스크립트 첫번째 버전의 버그이나 기존 코드에 영향을 줄 수 있기 때문에 아직 수정되고 있지 않다고함
따라서 값이 null 타입인지 확인할 때는 typeof 연산자를 사용하는 것보다 일치 연산자(===) 사용을 권하고 있음
var foo = null;
typeof foo === null; // false
foo === null; // true
// type of 연산자
console.log(typeof 210822);
console.log(typeof "Deep Dive");
console.log(typeof true);
// 자바스크립트는 소수와 정수 구별하지 않음
// 1과 1.0 모두 number로 출력
console.log(typeof 1);
console.log(typeof 1.0);
// 아래 3개는 모두 String으로 출력
console.log(typeof "1");
console.log(typeof "1");
console.log(typeof `1`);
// 변수나 함수에서도 활용 가능
let a = "Hello";
function sayHello() {
console.log("Hello");
}
console.log(typeof a);
console.log(typeof sayHello);
// typeof 연산자는 사칙연산보다 순위가 높음
// + 연산자보다 typeof가 먼저 실행되어 String이 되고 이후 +연산자 실행
console.log(typeof "Hello" + "Deep Dive");
// typeof 8은 문자열 Number가 되기 때문에
// 문자열과 숫자의 연산으로 NaN
console.log(typeof 8 - 3);
//해결하려면 사이에 괄호를 넣어주면 됨
- 마지막으로 하나 더 주의할 점은, 선언하지 않은 식별자를 typeof 연산자로 연산 시 ReferenceError가 발생하지 않고 undefined가 반환됨
// undeclared 식별자 선언한 적이 없음
typeof undeclared; // undefined
7.9 지수 연산자
ES7 도입, 거듭제곱
도입 전에는 Math.pow 메서드 사용해옴
// 거듭제곱
console.log(2 ** 3); // 8
// 음수를 거듭제곱의 밑으로 사용하려면 괄호로 묶어야함
console.log((-5) ** 2); // 25
// 할당 연산자와 함게 사용 가능
let numb = 5;
numb **= 2; // 25
지수연산자가 Math.pow 보다 가독성이 더 좋을 때
Math.pow(2,3)
8
2 ** 2 ** 2
16
Math.pow(Math.pow(2,2),2)
16
7.10 그 외
7.11 연산자 우선순위
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Operators/Operator_Precedence#표
21이 가장 우선