[완벽 가이드] 4장. 표현식과 연산자

Ninto·2023년 1월 1일
0

학습 기록

목록 보기
14/17

  • : 표현식이 평가되어 생성된 결과
  • 리터럴 : 사람이 알아볼 수 있는 문자나 기호를 사용해 값을 생성하는 표기법
  • 표현식 : 값으로 평가 될 수 있는 문 (표현식은 평가된 값을 반환함)
  • : 프로그램을 구성하는 최소 실행 단위

표현식인지 문인지 확인하는 방법은 크롬 콘솔을 사용하면 편리하다.

let num = 10; //할당문 undefined
num //기본 표현식 10
100 + num; //표현식 110
num = 100; //할당문 100

📌 기본 표현식

표현식이란 어떤 값(value)으로 평가되는 구절이다.

가장 단순한 표현식을 기본 표현식이라 한다.

상수나 리터럴 값, 일부 키워드(예약어), 변수 참조 등...
기본 표현식은 자신보다 더 단순한 표현식을 포함하고 있지 않는다.

1.23 //숫자 리터럴
'hello' // 문자열 리터럴
/pattern/ //정규표현식 리터럴 
true // boolean true 값으로 평가됨
false // boolean false 값으로 평가됨
null // null로 평가됨
this // '현재' 객체로 평가됨 (위치에 따라 상대적으로 값이 평가됨)
i // 변수 i의 값으로 평가
sum // 변수 sum의 값으로 평가
undefined // 전역객체의 undefined 프로퍼티 값
...

자바스크립트에서는 변수 참조시 식별자를 통해 값에 접근(참조)하려 하므로,
만약 그 식별자가 존재하지 않는다면, ReferenceError(참조에러)가 발생한다.



📌 배열과 객체의 초기화 표현식

배열과 객체의 초기화 표현식(initializer)은 그 값이 새로 생성된 배열이나 객체인 표현식이다.
(배열 리터럴, 객체 리터럴 등...)

초기화 표현식은 프로퍼티와 요소 값을 지정하는 다양한 하위 표현식으로 구성되므로 기본 표현식이 아니다.


🔗 배열 초기화 표현식

(= 배열 리터럴)

대괄호([]) 안에 콤마(,)로 구분된 리스트를 쓰는 형태의 표현식

배열 초기화 표현식의 값은 새로 생성된 배열이며,
새 배열의 요소는 콤마로 구분된 표현식들의 값으로 초기화 된다. (요소 표현식)

요소 표현식은 배열 초기화 표현식을 평가할 때마다 평가된다.

[] // 빈 배열, 대괄호안에 표현식이 없다면 요소가 없다는 의미(값이 없는 빈배열이다.)
['a'] //' a'라는 요소 하나를 가지고 있는 배열
[1+2, 3+4] // [3, 7] 3과 7이라는 요소 2개를 가지고 있는 배열
let arr = [[1,2], [3,4], [5,6]] //배열안의 요소 표현식이 배열 초기화 표현식이 될 수 있다.(중첩 배열 가능)
[1,,,5] // [1, undefined, undefined, 5] (콤마를 기준으로 생략된 값이 들어가면 undefined로 값이 평가됨)
let a = [1,] // a.length 는 1이 나옴 (마지막 요소표현식 다음에 콤마가 단 하나 있으면 요소는 만들어지지 않음)

🔗 객체 초기화 표현식

(= 객체 리터럴)

중괄호({})안에 프로퍼티 이름과 콜론(:)을 쓰는 형태의 표현식

객체 리터럴 문법은 ES6이후에 다양해졌기 때문에, 추후 더 자세히 공부하길 권장한다.
배열 초기화 표현식과 같이 중첩이 가능하다. (배열 안에 배열, 객체 안에 객체가 가능)

let obj1 = {} // 프로퍼티가 없는 빈 객체
let obj2 = {x: 1, y: 2} // 프로퍼티가 2개인 객체
obj1.x = 1; obj1.y = 2; //obj1에 x와 y 프로퍼티를 추가
obj1.x === obj2.x //true
let obj3 = {obj1: {}, obj2: {x:1, y:2}}; //객체 안의 요소 표현식이 객체 초기화 표현식이 될 수 있다.


📌 함수 정의 표현식

(= 함수 리터럴)

함수를 정의하며 그 값은 함수인 표현식이다.

함수 리터럴 문법 또한 다양하기 때문에, 추후 더 자세히 공부하길 권장한다.
(함수표현식, 함수선언, 화살표함수 ... )

일반적으로 function 키워드로 시작하고 괄호(())안에 0개 이상의 식별자(매개변수)를 쓴 다음, 중괄호({})안에 코드를 작성하는 형태이다.

let square = function(x) { return x * x } // 전달받은 값의 제곱을 반환해주는 함수 (함수 표현식)


📌 프로퍼티 접근 표현식

프로퍼티 접근 표현식은 객체 프로퍼티나 배열 요소의 값으로 평가된다.

자바스크립트에서는 일반적으로 프로퍼티에 접근하는 2가지 프로퍼티 접근 문법이 있다.


🔗 dot notation

표현식(객체) 뒤에 마침표(.)을 쓰고 그 뒤에 식별자(프로퍼티) 작성하는 형식

접근하고자 하는 이름이 유효한 식별자이고, 그 이름을 알고 있을 때만 사용 가능하다.

expression.identifier
//예시
let obj = {x:1, y:{z: 3}}
let arr = [obj, 4, [5, 6]] //obj객체를 담고 있는 배열

obj.x // 1 표현식 obj의 프로퍼티 x에 접근하여 1이라는 값으로 평가됨
obj.y.z // 3 표현식 obj.y의 프로퍼티 z에 접근하여 3이라는 값으로 평가됨
arr[0].y.z // 3 표현식 arr의 0번째 인덱스에 있는 객체 obj.y의 프로퍼티 z에 접근하여 3이라는 값으로 평가됨 

🔗 bracket notation

표현식(객체나 배열)뒤에 대괄호([])를 쓰고 그 안에 다른 표현식을 쓰는 형식

프로퍼티 이름에 공백이나 점이 들어가있거나, 숫자인 경우(배열), 프로퍼티 이름이 고정되어 있지 않고 계산 결과일 때에는 반드시 대괄호 표기법을 사용해야한다.

expression[expression]
//예시
let obj = {x:1, y:{z: 3}}
let arr = [obj, 4, [5, 6]] //obj객체를 담고 있는 배열

obj['x'] //1 객체의 프로퍼티에 대괄호 표기법으로 접근하려면 문자열로 감싸서 접근해야한다.
arr[2][1] //6 배열의 경우 인덱스 숫자만 작성해도 접근이 가능하다.

🔗 조건부 프로퍼티 접근

(= optional chaining, 옵션 체인이라고도 함)

ES2020에서 새롭게 추가된 프로퍼티 접근 표현식이다.

?. 이나 ?.[] 을 사용해 접근하려는 표현식이 null이나 undefined로 평가될 때 발생하는 TypeError를 막아준다.

마침표나 대괄호 표기법으로 null이나 undefined로 평가되는 표현식에 접근하면 TypeError가 발생하지만, 조건부 표기법을 사용하면 undefined로 값이 평가된다.

즉, 중첩된 object 자료에서 에러없이 안전하게 자료를 뽑을 수 있음.

let obj = {name: 'kim'}
obj.name
obj?.name //obj.name과 같은 값 이기때문에 굳이 점하나를 이용해서 접근할땐 사용하지 않아도 됨
obj.age?.num //undefined , obj.age가 undefined이지만 type에러가 발생하지 않음


📌 호출 표현식

주로 표현식 뒤에 괄호(())를 쓰고, 그 안에 콤마(,)로 구분된 0개 이상의 함수 인자 표현식 리스트를 쓴다.

호출 표현식은 함수나 메서드를 호출(실행)하는 문법이다.

호출 표현식을 평가할 때는 아래와 같이 3단계의 과정을 거친다.

  1. 함수 표현식을 평가 //표현식이 함수가 아니라면 TypeError가 발생
  2. 함수 인자 표현식을 평가 후 인자 값 리스트 생성
  3. 그 인자값을 매개변수 순서대로 할당 후 호출 표현식의 값으로 반환

호출 표현식의 값을 반환할때 실행되는 함수 내부에서 return이 있다면, return 값으로 반환하고
return이 존재하지 않는다면 호출 표현식의 값은 undefined가 된다.

호출 표현식의 맨 앞에 있는 표현식이 프로퍼티 접근 표현식이라면 이 호출은 메서드 호출이라고 한다.
이때, 호출 표현식의 값으로 반환되는 값은 this 키워드의 값이 된다.

//예시
f(0) //f 는 함수 표현식이고, 0은 인자 표현식이다.
Math.max(x,y,z) //Math.max는 함수(Math객체의 max라는 메서드)이고 x,y,z는 인자이다.
a.sort() //a는 함수이고 인자는 없다.

🔗 조건부 호출

조건부 프로퍼티 접근이 가능한 것처럼 조건부 호출도 가능하다.

함수를 호출할 때 표현식 뒤에 ?.() 를 붙여 호출한다.

호출할 값이 존재할 때만 호출하며 에러가 발생하지 않는다.



📌 객체 생성 표현식

객체를 생성하고 함수(생성자)를 호출하여 객체 프로퍼티를 초기화한다.
주로 new라는 키워드를 앞에 붙인다.

생성자 함수에 전달할 인자가 없다면 괄호는 생략이 가능하다.
객체 생성 표현식의 값은 새로 생성된 객체이며, 생성자에 대해 추후에 더 자세히 살펴보도록 하자.

//생성 표현식의 예시

new Object() //새로운 객체 생성
new Object // 괄호 생략 가능
new Date
new Array()
new Point(2,3)
...


📌 연산자

연산자에는 우선 순위가 존재하며 부호나 키워드로 이루어져 있다.

연산자는 주로 산술, 비교, 할당 표현식 등에 사용된다.

🔗 연산자 우선순위와 평가순서

자주 사용되는 연산자들의 우선 순위를 알아보자.
우선 순위가 높을수록 실행(평가)되는 순서가 빠르다.

괄호 > 증감, 부정연산자 > 산술연산자 > 비교연산자 > 동치연산자 > 논리연산자 > 할당연산자

우선순위연산자동작
1++전위(후위) 증가
1--전위(후위) 감소
1!불 값을 반대로 변환
1delete프로퍼티 제거
1typeof피연산자의 타입을 반환
2**지수 연산자(제곱)
3*, /, %곱셈, 나눗셈, 나머지
4+, -덧셈(or 문자열 병합), 뺄셈
5<< , >>, >>>시프트 비트연산자
6<, <=, >, >=(숫자 or 문자-알파벳순서)비교연산자
6instanceof객체 클래스 체크
6in프로퍼티가 존재하는지 체크
7==, !=, ===, !==동등,일치 연산자
8&&논리 and 연산자
9||논리 or 연산자
10??null 병합 연산자
11?:조건 연산자
12=할당 연산자
13+=, -=, *=, /= 등연산 후 할당

🔗 피연산자와 결과타입

피연산자가 특정 타입일 것으로 간주하며 특정 타입의 값을 반환한다.

이때 연산자에 의한 암묵적 타입변환이 발생할 수 있다.

대표적인 예시로는 + 연산자가 이항 연산에 사용될 때의 형변환을 볼 수 있다.

1 + 2 // 3 숫자와 숫자 이항 연산시에는 숫자의 덧셈으로 산술 연산한다.
1 + '2' // 12 좌항에 있는 숫자 1을 문자 1로 형변환하여 문자끼리의 병합으로 연산한다.

+연산자의 경우 단항 연산에 사용시 숫자타입을 우선시하지만, 이항 연산시에는 문자타입을 우선시하여 문자타입이 하나라도 포함되있을시 문자열 병합으로 처리된다.

반면, -, *, / 등의 연산자는 숫자타입을 우선으로 한다.

3 * 5 // 15
'3' * '5' //15 문자타입인 3과 5를 숫자타입으로 변환하여 산술연산을 한다.

이 외에도 ==!= 연산자 사용시 암묵적 타입변환이 일어나서 타입에 상관없이 값만 비교가 일어나기 때문에 사용을 지양해야 한다.

'10' == 10 //true 암묵적 타입변환이 발생함
'10' === 10 //false 타입이 다르기때문에


📌 null 병합 연산자

(= nullish coalescing 연산자)

주로 a ?? b 처럼 ??을 사용하며,
왼쪽에 있는 표현식이 undefined나 null이면 오른쪽에 있는 값을 반환한다.

ES2020에 새롭게 추가되었으며, 주로 변수에 외부 데이터를 받아올 때(입력값) 시간이 걸리는 경우 undefined로 표시되는 값을 다른 값으로 지정하기 위해 사용됨.

let obj = {};
obj.a ?? '없음' //'없음' obj에 a라는 프로퍼티가 undefined이기 때문에 '없음'이라는 값이 반환됨


📌 단축평가

단축평가는 표현식을 평가하는 도중에 평가 결과가 확정된 경우 나머지 평가 과정을 생략한다.

단축평가를 이용하여 if문을 대체할 수 있다.

논리연산자에는 논리곱연산자와 논리합 연산자를 통한 단축평가가 존재한다.
논리 연산의 결과를 결정하는 피연산자를 타입 변환하지 않고 그대로 반환함.

  • 논리곱(&&) 연산자 : 앞에가 있어야 비로소 뒤에걸 쓰겠다.
  • 논리합(||) 연산자: 앞에가 있으면 앞에걸, 앞에가 없으면 뒤에걸 쓰겠다.
  • null 병합연산자: 앞에가 없으면 뒤에걸 쓰겠다.

아래의 코드를 실행하면 무슨 값이 나오는지 살펴보자.

let a = {
	value: 0
}

let aa1 = a.value || '없음';
let aa2 = a.value ?? '없음';
let aa3 = a.value && '없음';

console.log(aa1); //'없음'
console.log(aa2); // 0
console.log(aa3); // 0


'cat' && 'dog' // 'dog'
'cat' || 'dog' // 'cat'
false || 'dog' // 'dog'
undefined ?? 'dog' // 'dog'
null ?? 'dog' // 'dog'


참고 자료

https://www.youtube.com/watch?v=WHUvtiKy_pg

profile
성장에는 성장통이 있기 마련이다.

0개의 댓글