관계 연산자는 두 값 사이의 관계('동등하다', '~보다 작다', '~의 프로퍼티')를 나타내며, 관계에 따라 항상 불린 값(true 또는 false)를 반환한다.
==
(동등 연산자, 느슨한 동치 연산자) : 값을 비교하며, type이 다른 경우 javascript에서 자동으로 변환하여 값만을 비교
console.log('1' == true); //true
===
(일치 연산자, 엄격한 동치 연산자) : 값과 type이 완전히 일치하는 지 비교
(===
만을 동치 연산자라고 부르는 경우도 있다.)
// 💡 특이 케이스
console.log(0 === -0); //true
console.log(NaN === NaN); //false
!=
비동등 연산자 : 두 값이 동등한 경우 false / 동등하지 않은 경우 true 반환
!==
불일치 연산자 :두 값이 완전히 일치하는 경우 false / 일치하지 않는 경우 true
[함께 읽으면 좋을 글] 자기 자신을 포함한 어떤 값과도 같지 않은 NaN
[함께 읽으면 좋을 글] 객체(배열)의 일치 비교
💡
==
,!=
는 자바스크립트의 구형 기능으로 버그를 낳는 것으로 악명이 높다. 되도록===
,!==
를 사용하는 것을 권장
<
, >
: 숫자의 크기 또는 문자의 순서를 비교한다.
숫자
와 문자열
만 비교가 가능하므로, 피연산자의 타입을 숫자 또는 문자열로 변환하여 비교한다.(valueOf(), toString() 매서드 반환 값 사용)console.log("11" < "3"); // true (문자열 비교; ASCII 값 '1'은 49, '3'은 51이다.)
console.log("11" < 3); // false (숫자 비교)
console.log("one" < 3); // false (숫자 비교; 'one'는 NaN으로 변환)
NaN
(이거나 NaN으로 변환된다면)이라면 결과는 항상(<, >, <=, >=) false
이다. String.toLowerCase()
또는 String.toUpperCase()
사용하여 비교)(문자열, 심벌 또는 문자열로 변환될 수 있는 값) in 객체
객체 안에 해당 프로퍼티 네임이 있다면 true
배열의 경우 해당 인덱스 번호가 있다면 true
let someObj = {x: 1, y: 2};
console.log('x' in someObj); // true
let someAry = ['a', 'b', 'c'];
console.log(0 in someAry); // true
console.log(5 in someAry); // false
console.table(someAry);
/*
┌─────────┬────────┐
│ (index) │ Values │
├─────────┼────────┤
│ 0 │ 'a' │
│ 1 │ 'b' │
│ 2 │ 'c' │
└─────────┴────────┘ */
객체 instanceof 객체의 클라스
객체
가 객체의 클라스
의 인스턴스라면 true, 아니면 false
let day = new Date();
console.log(day instanceof Date); // true (day는 Date()를 통해 생성됨)
console.log(day instanceof Object); // true (객체는 모두 Object의 인스턴스)
console.log(day instanceof Number); // false (day는 Number 객체가 아님)
boolean 값 연산 : 둘 중 하나라도 false면 false 반환
두 관계 표현식 연결
null
, undefined
, -0
, 0
, NaN
, ""
" "
, []
, {}
왼쪽 값이 Truthy(true로 해석되는 값)하면 오른쪽 값 리턴,
왼쪽 값이 Falsy(False로 해석되는 값)하면 왼쪽 값을 리턴한다.
console.log("자바스크립트" && "JavaScript"); // JavaScript
console.log(NaN && 1); // NaN
console.log(null && undefined) // null
console.log('0' && NaN); // NaN
let p = null;
console.log(p && p.x); // null
// p.x를 평가했다면 TypeError가 발생하지만, 왼쪽 값이 false이므로 더 이상 평가하지 않고 false 반환
if(a === b){
myFunction();
} // a === b 일 때만 myFunction()을 호출한다.
(a===b) && myFunction(); // a===b일 때만 myFunction()을 호출한다
💡 || 연산자보다 && 연산자가 우선순위가 높다
연산자 우선순위
console.log(true || false && false); // true
console.log((true|| false) && false); // false
소괄호를 활용해 우선순위를 명확히 하는 습관을 들이는 것이 좋다.
console.log(0 || true); // true
console.log({} || 123); // {}
console.log(null || undefined); // undefined
let max = maxWidth || preferences.maxWidth || 500;
// maxWidth가 true이면 사용,
// 그렇지 않다면 preferences 객체에서 true 값을 찾고,
// 그것도 안되면 500 으로 지정
function print(value){
const message = value || `아무것도 입력 안함`;
console.log(message);
}
print(); // 아무것도 입력 안함 (아무것도 입력 안한 falsy 값이여서 오른쪽 리턴)
print('JavaScript'); // JavaScript
피연산자를 boolean 값으로 변환한 뒤 그 반대 값을 리턴한다.
!!
으로 사용하는 경우 피연산자의 원본 boolean 값을 확인할 수 있다.
//드 모르간의 법칙도 논리표현식으로 표현할 수 있다.
!(p && q) === (!p || !q) // true
!(p || q) === (!p && !q) // true
lvalue(변수, 객체의 프로퍼티, 배열의 요소) =
(어떤 타입, 값 모두 가능)
=
의 우선 순위가 매우 낮으므로, 다른 식 안에서 먼저 사용할 때에는 ( )
를 함께 사용해야한다
우결합성(동일 우선순위에서 오른쪽에서 왼쪽으로 진행된다.
let x = y = z = 0;
let x = (y = (Z = 0));
연산자 | 예제 | 동등한 표현식 |
---|---|---|
+= | a += b | a = a+b |
-= | a -= b | a = a-b |
*= | a *= b | a = a*b |
/= | a /= b | a = a/b |
%= | a %= b | a = a%b |
**= | a **= b | a = a**b |
연산자 | 예제 | 동등한 표현식 | 뜻 |
---|---|---|---|
&&= | a &&= b | a && (a = b) a = a&&b | a의 boolean값이 true이면 경우 a에 b를 할당 |
||= | a ||= b | a || (a = b) a = a || b | a의 boolean값이 false이면 a에 b 할당 |
??= | a ??= b | a가 null 또는 undefined 이면 a에 b 를 할당(또는 b를 수행) |
let a = 1, b = 2;
a &&= b;
console.log(a); // 2
let x = 0, y = 1;
x ||= y;
console.log(x); // 1
0 ||= console.log('0의 불린 값은 flase'); // 0의 불린 값은 flase
let z = undefined;
z ??= console.log("z는 nullish값이다"); // z는 nullish값이다
z ??= 1;
console.log(z); // 1
조건 ?
true 일 때 동작 :
false일 때 동작
자바스크립트에서 유일한 3항 연산자이다.
if 조건문을 보다 간결하다.
let greeting1 = 'hello ' + (username ? username : 'there);
let greeting2 = 'hello ';
if (username){
greeting2 += username;
} else{
greeting2 += 'there';
}
💡조건연산자는 표현식이기 때문에
- 조건에 따른 변수 선언이나, 조건에 따른 반복문을 실행할 수는 없다.
(즉, 조건 연산자 안에는 변수 선언문, 반복문을 넣을 수 없다)
따라서모든 조건문을 대체할 수는 없다
는 한계가 있다.
왼쪽 피연산자가 null 이나 undefined 가 아니면 그 값을 반환하고,
null 이나 undefined 이면 오른쪽 피연산자의 값을 반환하다.
오른쪽 피연산자의 값은 null 이나 undefined 여도 관계 없다.
다른 부수 효과가 없는 식안에서라면
(a !== null && a !== undefined) ? a : b
와 동일하다.
console.log(0 ?? 1); // 0
console.log("" ?? 1); // (공백)
console.log(false ?? 1); // false
console.log(null ?? undefined); // undefined (왼쪽값이 null 이므로 오른쪽 값 반환)
??
대신 ||
를 사용하는 경우 false로 평가되는 값(0
, ""
, false
) 에서 오른 쪽 값이 결과값이 된다.
??
와 &&
, ||
의 우선 순위는 명확하지 않아, ( )
를 생략하는 경우 SyntaxError가 발생한다.
let a = null, b = 0, c = 1;
console.log((a ?? b) || c); // 1
console.log(a ?? (b || c)); // 1
console.log(a ?? b || c); // SyntaxError: missing ) after argument list
피연산자의 타입을 확인할 수 있다.
값 | typeof 연산자 결과 |
---|---|
undefined | undefined |
null | object |
true 또는 false | boolean |
숫자 또는 NaN | number |
BigInt 전체 | bigint |
문자열 전체 | string |
심벌 전체 | symbol |
함수 전체 | function |
함수가 아닌 객체 전체 | object |
객체 클래스를 구별하려면 instanceof 연산자, class 속성, constructor 프로퍼티 등 다른 방법을 사용해야 한다.
객체 프로퍼티나 배열 요소를 삭제한다.
배열의 요소를 삭제해도 배열의 길이가 변하지는 않는다.
삭제된 프로퍼티나 배열의 요소에 undefined 값이 할당되는 것은 아니지만, 해당 프로퍼티나 배열을 읽으면 undefined가 반환된다.
let ary = [1, 2, 3]
console.log(ary.length); // 3
delete ary[2];
console.log(ary.length); // 3
console.log(ary[2]); // undefined
피연산자를 성공적으로 삭제하면 true를 반환한다.
만약 피연산자가 프로퍼티나 배열의 인덱스가 아니라면 아무 행동도 취하지 않고 true를 반환한다.
let x = { a: 1 };
console.log(delete x.a);
console.log(delete x.b);
만약 삭제할 수 없는 프로퍼티를 삭제하려고 하면 fale가 반환된다.
strict mode에서 delete로 유효하지 않은 식별자를 넘기면 SyntaxError가 발생한다
strict mode에서 삭제할 수 없는 프로퍼티를 삭제하려고 하면 TypeError가 발생한다