(4장) 표현식과 연산자 - 9. 관계표현식 ~ 13. 기타 연산자[자바스크립트 완벽 가이드 7판]

iberis2·2023년 1월 2일
0

4장 표현식과 연산자

9. 관계 표현식

관계 연산자는 두 값 사이의 관계('동등하다', '~보다 작다', '~의 프로퍼티')를 나타내며, 관계에 따라 항상 불린 값(true 또는 false)를 반환한다.

  • if, while, for문과 같은 제어문에서 주로 사용된다.

9-1. 일치와 불일치 연산자

== (동등 연산자, 느슨한 동치 연산자) : 값을 비교하며, type이 다른 경우 javascript에서 자동으로 변환하여 값만을 비교

console.log('1' == true); //true

=== (일치 연산자, 엄격한 동치 연산자) : 값과 type이 완전히 일치하는 지 비교
(===만을 동치 연산자라고 부르는 경우도 있다.)

// 💡 특이 케이스
console.log(0 === -0); //true
console.log(NaN === NaN); //false

!= 비동등 연산자 : 두 값이 동등한 경우 false / 동등하지 않은 경우 true 반환
!== 불일치 연산자 :두 값이 완전히 일치하는 경우 false / 일치하지 않는 경우 true

[함께 읽으면 좋을 글] 자기 자신을 포함한 어떤 값과도 같지 않은 NaN
[함께 읽으면 좋을 글] 객체(배열)의 일치 비교

💡==, !=는 자바스크립트의 구형 기능으로 버그를 낳는 것으로 악명이 높다. 되도록 ===, !==를 사용하는 것을 권장

9-2. 비교 연산자

<, > : 숫자의 크기 또는 문자의 순서를 비교한다.

  • 어떠한 타입의 피연산자도 typeError가 발생하지 않는다.
  • 다만 숫자문자열만 비교가 가능하므로, 피연산자의 타입을 숫자 또는 문자열로 변환하여 비교한다.(valueOf(), toString() 매서드 반환 값 사용)
  • 두 연산자 모두 문자열일때만 문자열 비교를 수행한다.
console.log("11" < "3"); // true (문자열 비교; ASCII 값 '1'은 49, '3'은 51이다.)
console.log("11" < 3); // false (숫자 비교)
console.log("one" < 3); // false (숫자 비교; 'one'는 NaN으로 변환)
  • 숫자 비교
    • 0과 -0은 같은 값
    • Infinity는 자기 자신을 제외한 어떠한 값보다 크고, -Infinity는 자기 자신을 제외한 어떠한 값보다 작다.
    • 피연산자들 중 하나라도 NaN(이거나 NaN으로 변환된다면)이라면 결과는 항상(<, >, <=, >=) false이다.
    • BigInt와 숫자 비교 가능
  • 문자 비교
    • ASCII(아키코드) 값을 비교
    • ASCII 소문자가 모두 대문자보다 크다.
      (대소문자 구분 없는 비교를 위해서는 String.toLowerCase() 또는 String.toUpperCase() 사용하여 비교)

9-3. in 연산자

(문자열, 심벌 또는 문자열로 변환될 수 있는 값) 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'   │
└─────────┴────────┘ */

9-3. instanceof 연산자

객체 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 객체가 아님)

10. 논리 표현식

10-1. && (AND)

  • boolean 값 연산 : 둘 중 하나라도 false면 false 반환

    • true && true // true
    • true && false // false
  • 두 관계 표현식 연결

  • 왼쪽 값이 Truthy(true로 해석되는 값)하면 오른쪽 값 리턴,
    왼쪽 값이 Falsy(False로 해석되는 값)하면 왼쪽 값을 리턴한다.

console.log("자바스크립트" && "JavaScript"); // JavaScript
console.log(NaN && 1); // NaN
console.log(null && undefined) // null
console.log('0' && NaN); // NaN
  • 단축 평가(short circuit) : 왼쪽이 falthy하면 오른쪽은 판단하지 않고 바로 왼쪽 반환
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

소괄호를 활용해 우선순위를 명확히 하는 습관을 들이는 것이 좋다.

10-2. || (OR)

  • 왼쪽 값이 Truthy(true로 해석되는 값)하면 왼쪽 값 리턴,
    왼쪽 값이 Falsy(False로 해석되는 값)하면 오른쪽 값을 리턴한다.
console.log(0 || true); // true
console.log({} || 123); // {}
console.log(null || undefined); // undefined
  • 단축 평가(short circuit) : 왼쪽이 truthy하면 오른쪽 표현식은 평가하지 않고 바로 왼쪽을 반환한다.
    • 가장 먼저 등장하는 true 값을 선택하는 경우 자주 사용
    • 함수의 매개변수의 truthy, falsy를 이용할 수도 있다.
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

10-3. ! (NOT)

피연산자를 boolean 값으로 변환한 뒤 그 반대 값을 리턴한다.
!! 으로 사용하는 경우 피연산자의 원본 boolean 값을 확인할 수 있다.

//드 모르간의 법칙도 논리표현식으로 표현할 수 있다.
!(p && q) === (!p || !q) // true
!(p || q) === (!p && !q) // true

11. 할당 표현식

lvalue(변수, 객체의 프로퍼티, 배열의 요소) = (어떤 타입, 값 모두 가능)

  • = 의 우선 순위가 매우 낮으므로, 다른 식 안에서 먼저 사용할 때에는 ( )를 함께 사용해야한다

  • 우결합성(동일 우선순위에서 오른쪽에서 왼쪽으로 진행된다.

let x = y = z = 0;
let x = (y = (Z = 0));

11-1. 할당과 연산

연산자예제동등한 표현식
+=a += ba = a+b
-=a -= ba = a-b
*=a *= ba = a*b
/=a /= ba = a/b
%=a %= ba = a%b
**=a **= ba = a**b
연산자예제동등한 표현식
&&=a &&= ba && (a = b)
a = a&&b
a의 boolean값이 true이면 경우 a에 b를 할당
||=a ||= ba || (a = b)
a = a || b
a의 boolean값이 false이면 a에 b 할당
??=a ??= ba가 null 또는 undefined 이면 a에 b 를 할당(또는 b를 수행)

할당 연산자 MDN

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

13. 기타 연산자

? : (조건연산자 또는 삼항연산자 Ternary operator)

조건 ? true 일 때 동작 : false일 때 동작
자바스크립트에서 유일한 3항 연산자이다.
if 조건문을 보다 간결하다.

let greeting1 = 'hello ' + (username ? username : 'there);
                       
let greeting2 = 'hello ';
if (username){
  greeting2 += username;
} else{
  greeting2 += 'there';
}

💡조건연산자는 표현식이기 때문에

  • 조건에 따른 변수 선언이나, 조건에 따른 반복문을 실행할 수는 없다.
    (즉, 조건 연산자 안에는 변수 선언문, 반복문을 넣을 수 없다)
    따라서 모든 조건문을 대체할 수는 없다는 한계가 있다.

?? (null 병합 연산자)

왼쪽 피연산자가 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 연산자

피연산자의 타입을 확인할 수 있다.

typeof 연산자 결과
undefinedundefined
nullobject
true 또는 falseboolean
숫자 또는 NaNnumber
BigInt 전체bigint
문자열 전체string
심벌 전체symbol
함수 전체function
함수가 아닌 객체 전체object

객체 클래스를 구별하려면 instanceof 연산자, class 속성, constructor 프로퍼티 등 다른 방법을 사용해야 한다.

delete 연산자

객체 프로퍼티나 배열 요소를 삭제한다.
배열의 요소를 삭제해도 배열의 길이가 변하지는 않는다.
삭제된 프로퍼티나 배열의 요소에 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가 발생한다

profile
React, Next.js, TypeScript 로 개발 중인 프론트엔드 개발자

0개의 댓글