Chapter 4. 표현식과 연산자

허상범·2023년 1월 2일
0
post-thumbnail

자바스크립트 완벽 가이드 7판 스터디
책의 목차를 따라가며 관련 내용을 학습하고 공유하는 스터디입니다.

... 그중에서도 기억할 만한 핵심을 추린다면 다음과 같습니다.

  • 표현식은 자바스크립트 프로그램의 구절(phrase)과 같습니다.
  • 표현식은 모두 자바스크립트 값으로 평가될 수 있습니다.
  • 표현식에는 값으로 평가되는 것 외에도 변수 할당 같은 부수 효과가 있을 수 있습니다.
  • 리터럴, 변수 참조, 프로퍼티 접근 같은 단순한 표현식을 연산자료 묶어서 더 큰 표현식을 만들 수 있습니다.
  • 자바스크립트 연산자는 크게 산술 연산, 비교, 불, 논리, 할당. 비트 조작 연산자로 나눌 수 있으며 이외에도 조건 연산자를 비롯해 기타 연산자가 더 있습니다.
  • 자바스크립트의 + 연산자는 숫자를 더할 때나 문자열을 병합할 때 사용할 수 있습니다.
  • 논리 연산자 &&와 ||에는 때에 따라 피연산자 중 하나만 평가하는 특별한 '단축 평가' 방식이 있습니다. 자바스크립트의 관용적 표현 중에는 이 연산자의 특별한 동작 방식을 이해해야 알 수 있는 것들이 있습니다.

자바스크립트 완벽 가이드 7판, p.111

1. 표현식(expression)이란?
2. 객체, 배열 초기화 표현식
3. 함수 정의 표현식
4. 프로퍼티 접근 표현식, 조건부 프로퍼티 접근
5. 호출 표현식, 조건부 호출
6. 연산자란? 피연산자, 부수 효과(Side Effect), 우선순위
7. 산술 표현식: +, -, /, *, %, ++, --
8. 관계 표현식: 동등 비교, in, instanceof
9. 논리 표현식: &&, ||, !
10. nullish


1. 표현식(expression)이란?

  • 어떤 값으로 평가되는 구절이다.
  • 단순한 상수, 변수의 이름부터 단순한 표현식을 연산자로 조합한 복잡한 표현식도 있다.
  • 모두 표현식이 평가되어 나온 결과(값)
  • ex) 함수의 반환 값, 변수에 할당된 값 등

기본 표현식

  • 상수나 리터럴 값, 일부 키워드, 변수 참조가 있다.
1.23456; // 숫자 리터럴
'Guide 7e' / // 문자열 리터럴
  pattern / // 정규 표현식 리터럴
  true; // true (Boolean)
false; // false (Boolean)
null; // null
this; // '현재' 객체

let i = (j = 1);
i; // 변수 i
j; // 변수 j

2. 객체, 배열 초기화 표현식

  • 초기화 표현식을 객체 리터럴이나 배열 리터럴이라고도 한다.

배열

  • 대괄호 [] 안에 콤마로 구분된 리스트를 쓰는 형태
  • 초기화 표현식의 값은 새로 생성된 배열이다.
  • 주의!! 비어있는 경우 고차함수의 내부 반복에서 제외
const arr1 = []; // 빈 배열;
const arr2 = [1, 2, 3, 4, 5 + 5]; // [1 ,2 ,3, 4, 10]
const arr4 = [
  [1, 2, 3],
  [4, 5, 6],
]; // 중첩 배열

const arr3 = [1, , , 4]; // [ 1, <3 empty items>, 4 ], 길이는 5

arr3.forEach((v, i) => {
  console.log(`index: ${i}, value: ${v}`);
});
// index: 0, value: 1
// index: 4, value: 4

console.log(arr3.map((v, i) => v * 10));
// [ 10, <3 empty items>, 40 ]

객체

  • 중괄호를 쓰고, 각 하위 표현식은 프로퍼티 이름과 :으로 시작한다.
let obj = {
  a: '111',
  b: '222',
  c: { d: '333', f: '444' },
};

3. 함수 정의 표현식

  • 일반적으로 function 키워드로 시작, 괄호 안에 0개 이상의 식별자, 중괄호 안에 자바스크립트 코드를 쓰는 형태
  • ES6에서 화살표 함수 문법 추가
function func1(x) {
  return x;
}

const func2 = function func1(y) {
  return y;
};

const func3 = z => z;

4. 프로퍼티 접근 표현식, 조건부 프로퍼티 접근

프로퍼티 접근 방법 2가지

expression.identifier; // 1. 표현식 . 식별자
expression[expression]; // 2. 표현식 [ 표현식 ]
  • 2가지 방식 전부 앞의 표현식을 먼저 평가
    • 그 값이 null, undefined 면 TypeError 반환
    • 뒤가 식별자면 식별자가 이름인 프로퍼티를 찾음
    • 뒤가 표현식이면 표현식을 평가해 문자열로 변환 -> 문자열이 이름인 프로퍼티를 찾음
    • 해당 프로퍼티가 존재하지 않는다면 undefined 반환
  • 보통 프로퍼티 이름이 고정되어 있지 않고 런타임에서 결정될 때 대괄호를 사용

조건부 프로퍼티 접근

  • ?.
expression?.identifier;
expression?.[expression];
  • 자바스크립트에서 프로퍼티를 가질 수 없는 값은 nullundefined 뿐이다.
    • 접근 시 TypeError가 발생한다.
  • ?.를 사용해 에러 발생을 막을 수 있다.
    • 만약 앞의 표현식이 null 이나 undefined 이라면 프로퍼티에 접근하려는 시도 없이 undefined로 평가 된다.
    • 하위 식별자 또는 표현식은 평가되지 않음 => 단축평가이다.
const outer = {
  valueNull: null,
  inner: { a: 1, b: 2 },
};

outer.valueNull.a; // TypeError: Cannot read properties of null (reading 'a')
outer.valueNull?.a; // undefined

5. 호출 표현식, 조건부 호출

호출 표현식

  • 함수나 메서드를 호출하는 문법이다.
  • 함수 표현식의 값이 함수가 아니라면 TypeError 발생
function func1(x) {
  return x * 100;
}

const variable = 100;

func1(1); // 100
variable(1); // TypeError: variable is not a function

Math.max(1, 2, 3); // Math 객체의 메서드 호출

조건부 호출

  • ES2020에서 추가
  • 4.의 조건부 프로퍼티 조건과 유사하다.
  • 함수가 아닌 것을 호출 표현식으로 호출하려고 하면 표현식 전체를 undefined로 평가한다.
function calculation(v1, v2, func) {
  return func(v1, v2);
}
calculation(5, 6, (a, b) => a * b); // 30
calculation(5, 6); // TypeError: func is not a function

function calculation2(v1, v2, func) {
  return func?.(v1, v2);
}
calculation2(5, 6, (a, b) => a + b); // 11
calculation2(5, 6); // undefined

6. 연산자란? 피연산자, 부수 효과(Side Effect), 우선순위

  • 책의 표 4-1 자바스크립트 연산자 참고
  • 연산자는 산술 표현식, 비교 표현식, 논리 표현식, 할당 표현식 등에 사용
  • 대부분 +, = 처러 부호로 표현, delete, instanceof 같은 키워드 연산자도 있음
  • 연산자는 우선순위가 존재하며 높은 것부터 실행(연산)한다.
  • 결합성은 오른쪽 -> 왼쪽 , 왼쪽 -> 오른쪽 두 가지이며, 우선순위가 같은 동작을 수행할 때의 순서이다.
    • ex) x - y + z 덧셈 뺼셈은 우선순위가 동등, 따라서 왼쪽부터 차례대로 연산 (x - y) + z
  • 결과 타입
    • 대부분 피연산자가 특정 타입일 것으로 간주하며 특정 타입의 값을 반환한다.
    • 필요에 따라 피연산자의 타입을 변환한다.
      • ex) '1' * 21 * 2, '1' + 2'1' + '2'
  • 부수 효과(Side Effect)
    • 일부 표현식에는 평가 결과에 영향을 미치는 부수 효과(Side Effect)가 있다.
    • 할당 연산자 =, 증가감소연산자 ++, -- 는 기존 값에 영향을 준다.

  • 할당은 우선순위가 아주 낮다. 거의 항상 마지막에 수행
  • 곱셈과 나눗셈은 덧셈과 뺄셈보다 우선순위가 높다.
  • 우선순위가 불확실하다면 괄호를 사용해서 순서를 명시적으로 표현하자

7. 산술 표현식: +, -, /, *, %, ++, --, **

기본 산술 연산자

  • **,*, /, %, -
  • 피연산자를 평가해서 필요하다면 숫자로 변환 후 계산한다.
  • 숫자가 아니며 숫자로 변환할 수도 없는 피연산자는 NaN으로 변환

+ 연산자

  • 문자열 병합에 우선순위가 있다.
  • 피연산자중 하나가 문자열, 또는 문자열로 변환할 수 있는 객체라면 => 문자열로 변환 후 병합
  • 피연산자가 둘 다 문자열이 아니라면 => 숫자(또는 NaN)으로 변환 후에 더하기

단항 산술 연산자

  • +, -, ++, --
  • 피연산자 하나의 값을 바꿔 새 값을 얻는다.
  • 모두 우선순위가 높다.
  • 필요하다면 피연산자를 숫자로 변환한다.

단항 플러스(+)

  • 피연산자를 숫자 또는 NaN으로 변환한 값을 반환
console.log(+1); // 1
console.log(+-1); // -1
console.log(+'string'); // NaN

단항 마이너스(-)

  • 필요한 경우 피연산자를 숫자로 변환한 다음 부호를 변경
console.log(-1); // -1
console.log(-(-1)); // 1
console.log(-'string'); // NaN

증감(++, --)

  • 피연산자를 숫자로 변환하고 1을 더하고 증가된 값을 피연산자에 할당
  • 피연산자의 앞에 있을 때 전위 증가 연산자
    • 필요한 연산을 하고 그 뒤 값을 증가시킴
  • 피연산자의 뒤에 있을 때 후위 증가 연산자
    • 값을 먼저 증가시키고 필요한 연산을 함
let a = 0;
let b = a++;
console.log(a, b); // 1, 0

let c = -5;
let d = ++c;
console.log(c, d); // -4, -4

8. 관계 표현식: 동등 비교, in, instanceof

동등 비교 관계 연산자 (==, !=, ===, !==)

  • == : 값이 같음
  • != : 값이 다름
  • === : 값과 타입이 둘 다 같음
  • !== : 값과 타입이 다름
  • ===, !==을 사용하자!!!
  • Boolean 값은 숫자로 변환해 비교

in 연산자

  • 왼쪽 피연산자가 오른쪽 객체의 프로퍼티 이름일 경우 true 반환
console.log('max' in Math); // true
console.log('length' in Array); // true
console.log('0' in Array); // false

instanceof 연산자

  • 왼쪽 피연산자가 오른쪽 객체의 인스턴스일 경우 true 반환
  • 클래스나, 생성자 함수로 인스턴스를 만들었을 때 오류방지를 하기 위해서도 씀
const arr = [1, 2, 3, 4];
const today = new Date();

console.log(arr instanceof Object); // true
console.log(today instanceof Date); // true
console.log(Date instanceof Object); // true

9. 논리 표현식: &&, ||, !

  • 단축평가가 되는 특징

조건문 안에서

  • Boolean 값으로 변환하여 평가함
  • && 모두 true여야 true, 아니면 false
  • || 모두 false여야 false, 아니면 true

조건문 밖에서

&&

  • truthy한 경우 설정
  • false인 값을 찾을 때까지 오른쪽으로 평가.
  • false인 값을 만나면 평가 종료, 값을 반환
  • 제일 끝까지 평가했다면 제일 끝에 값을 반환
const zero = 0;
const one = 1;
const two = 2;

const result1 = one && two && zero; // zero에서 종료
const result2 = one && two; // two에서 종료
const result3 = one && zero && two; // zero에서 종료

console.log(result1); // 0
console.log(result2); // 2
console.log(result3); // 0

const user = {
  name: 'husbumps',
  email: null,
};

user.name && console.log('이름 정보가 있습니다.');
user.email && console.log('이메일 정보가 있습니다.');

// 이름 정보가 있습니다.

||

  • falsy한 경우 설정
  • true인 값을 찾을 때까지 오른쪽으로 평가.
  • true인 값을 만나면 평가 종료, 값을 반환
  • 제일 끝까지 평가했다면 제일 끝에 값을 반환
const user = {
  name: 'husbumps',
  email: null,
};

user.name || console.log('이름 정보가 없습니다.');
user.email || console.log('이메일 정보가 없습니다.');

// 이메일 정보가 없습니다.

10. Nullish

  • null, undefined 만 골라낼 수 있다!
  • ES2020에서 추가
  • falsy한 경우를 설정할 때 ||를 사용하면 빈 문자열, 0 같은 경우도 전부 falsy한 값이라 의도한대로 동작하지 않는 경우가 생긴다.
// num에 값이 할당되지 않은 undefined인 경우에 -1를 반환하고 싶을 때

let num = 0;

console.log(num || '-1'); // -1 => 의도하지않은동작
console.log(num ?? '-1'); // 0 => num에 0이 할당되었기때문에 제대로 동작


참고자료

0개의 댓글