Notice
Recent Posts
Recent Comments
Link
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
Archives
Today
Total
관리 메뉴

과거의 내가 미래의 나에게

딥다이브 :: 데이터 타입 & 연산자 & 제어문 & 단축평가 본문

js 이론

딥다이브 :: 데이터 타입 & 연산자 & 제어문 & 단축평가

양바삭 2023. 1. 1. 15:01

「딥다이브 자바스크립트」 정리 - 데이터 타입 & 연산자 & 제어문& 단축평가

※ 아래 내용은 책을 통해 학습한 것을 개인적으로 정리한 것으로 내용이 다소 부정확 할 수 있습니다.

 

 


1. 데이터 타입

js의 데이터 타입엔 원시(숫자, 문자열, 불리언, undefined, null, 심벌), 객체가 있다.

타입 종류

1. 숫자

C나 자바의 경우 정수와 실수를 구분해서 다양한 숫자 타입(int,long,float…)을 제공하지만 js는 실수로 처리하여 하나의 숫자 타입만 제공한다. 따라서 정수로 표시되는 수끼리 나누더라도 실수가 나올 수도 있는 것이다.

숫자 타입은 실수 외에 Infinity, -Infinity, NaN도 존재한다.

 

2. 문자열

문자열 표기법으로 “”,’’,``으로 텍스트를 감싸는데 가장 일반적인 것은 작은 따옴표이다.

C는 문자의 배열로, 자바는 문자열을 객체로 표현하지만 js는 문자열이 원시타입이다.

< \r\n은 자주 보던 것인데? >
* \n : 라인 피드(Line Feed). 타자기에서 커서를 정지한 상태에서 종이를 한 줄 올리는 것
* \r : 캐리지 리턴(carriage Return). 타자기에서 종이를 움직이지 않고 커서를 맨 앞줄로 이동하는 것.
타자기에서 근원한 것으로, 현재는 운영체제마다 다른 체계의 개행 방식을 이용한다. 윈도우는 CR과 LF로 새 줄을, 유닉스는 LF로, MAC은 LF를 사용한다. js는 LF, CR 모두 개행을 의미하지만 보통 LF로 개행한다.

* 이스케이프 시퀀스: 일반 문자열 내에서 공백을 표현할 때 등 사용되는 것. 백슬래쉬로 시작한다. 

 

3. undefined / null

undefined는 의도적으로 할당하려는 것이 아니라 js 엔진이 변수를 초기화할 때 사용하는 값.

의도적으로 변수에 값이 없음을 나타내고 싶을 때는 null을 사용하여야 한다.

 

4. Symbol

심벌 값은 유일무이한 값으로 객체의 유일한 프로퍼티 키를 만들기 위해 사용한다. 심벌 이외의 원시값은 리터럴을 통해 생성하지만 심벌은 Symbol 함수를 호출해 생성한다.

 

데이터 타입이 나뉘어져 있는 이유

특정 값을 메모리에 저장할 때 js엔진은 값의 데이터 타입에 따라 정해진 메모리 공간을 확보함으로 메모리 공간을 낭비없이 사용한다. 또한 특정 값을 참조할 때도, 얼만큼의 메모리 공간을 읽어들여야 할 것인가에 대해 데이터 타입을 통해 미리 알 수 있게 된다.

 

변수 값의 데이터 타입

js는 동적 타입 언어이다. 변수를 선언할 때 타입을 결정하는 정적 타입과 달리 변수에 값을 할당할 때 그 타입이 결정되므로 재할당으로 언제든지 자유롭게 타입이 변경될 수 있다.

 

동적 타입 언어는 편리성과 유연성은 높지만 신뢰성은 떨어진다. 값의 변경에 의해 언제든지 타입이 변경될 수 있어 값을 확인하기 전까지는 타입을 확신할 수 없고, 개발자의 의도와 다르게 엔진에 의해 암묵적으로 타입이 변환될 수도 있다.

개발자가 고려해야할 요소를 제해줌으로 편리해졌을 수도 있지만, 결국 개발자가 의도한대로 나오지 않은 코드는 언제나 불안감을 가지고 있는 요소가 될 것이다. 개발의 편리함보다는 코드의 확실한 신뢰가 더 중요하다고 여기기에 타입스크립트가 나온 것일지도.

 


2. 연산자

단항 산술 연산자

1. ++test

let test = 5
let result;

result = ++test
console.log(result, x) // 6, 6

2. test++

let test = 5
let result;

result = test++
console.log(result, x) // 5, 6

3. +단항 연산자

숫자 타입이 아닌 피연산자에 붙이면 숫자 타입으로 변환된다. 이는 암묵적 타입 변환 또는 타입 강제 변환이라고도 한다.

let test1 = '1'
let test2 = true
console.log(+test1, +test2) //1, 1

동등 비교 연산자

일치 비교 연산자에서 NaN은 자신과 일치하지 않는 유일한 값이다. 그러므로 빌드인 함수인 Number.isNaN()를 사용해야한다.

NaN === NaN //false
Number.isNaN(NaN) // true

혹은 ES6에서 나온 Object.is(a,b)를 사용하면 정확한 비교 결과를 반환한다.

Object.is(NaN,NaN) // true

삼항 조건 연산자

이는 결국 조건문인데, if문과 차이가 있다면 삼항 조건 연산자는 값으로 평가할 수 있는 표현식인 문이다. 따라서 이는 값처럼 다른 표현식의 일부가 될 수 있다.

let restult = if(x){retrun 'ㅇㅋ'} else {return 'ㄴㅋ'} // SyntaxError
let result = x ? 'ㅇㅋ':'ㄴㅋ' // 'ㅇㅋ'

// 경우의 수가 세 가지 인경우에도 사용할 수 있다.
let test = x ? (y ? 'ㅇㅋ':'ㄷㅋ') : 'ㄴㅋ'
< 드 모르간 법칙을 이용한 논리연산자 표현식 >
(!x && !y) === !(x || y)
(!x || !y) === !(x && y)

3. 제어문

블록문

블록문은 0개 이상의 문을 중괄호로 묶은 것. 이는 문의 종료를 의미하는 자체 종결성을 갖기 때문에 끝에 세미콜론을 붙이지 않는다.

조건문

  • if else 
  • switch

반복문

  • for 
  • while
  • do…while

break문

레이블 문, 반복문, switch문에서 코드 블록을 탈출한다.

* 레이블문: 식별자가 붙은 문이다.

// test라는 식별자가 붙은 레이블문
test: console.log(3) 

// 중복 for문에서 레이블을 이용한 break
outer: for(let i = 0; i<5; i++){
	inner: for(let j =0; j<5; j++){
  	if(i === 1 && j === 2){
    	break outer
    }
    console.log(i,j)// 0, 0 // 0, 1 여기서 바로 끝남
  }
}

continue문

continue가 있는 시점에서 실행을 중단시키고 반복문의 증감식으로 이동한다. if문에서 실행해야 할 코드가 여러줄이라면 들여쓰기가 한단계 깊어지므로 continue 문을 사용하여 가독성을 높일 수 있다.

for(let i = 0; i<5; i++){
	if(i !== 2) continue; // i가 2가 아니면 아래로 가지도 않는다. 
	//code...
	//code...
}

3. 타입 변환과 단축 평가

기존 원시값의 타입을 변경하더라도 기존의 값이 변경되는 것은 아니고, 원시값은 변경 불가능한 값이라 변경되지 않고 다른 타입의 새로운 원시 값을 생성한다.

암묵적 타입 변환

js의 암묵적 타입 변경은 개발자의 의도가 들어가지 않으므로 파악할 수 없는 오류의 여지가 많다. 그러므로 자신이 작성한 코드에서 암묵적 타입이 발생할 수 있는지, 발생한다면 어떤 타입의 어떤 값으로 변환되는 지, 그 변환된 값으로 표현식이 어떻게 평가될지 예측할 수 있어야 한다. 이를 위해 타입 변환이 언제 어떻게 일어나는지 명확히 알고 있어야 할 것이다.

 

1. 문자열

문자열 연결 연산자 표현식에서 피연산자가 문자열이 아니면 에러를 피하기 위해 이를 문자열로 암묵적으로 변환시킨다.

0 + '' = '0'
true + '' = 'true'
({}) + '' = '[object object]'

2. 숫자열

비교 연산자 혹은 산술 연산자를 사용할 때 피연산자가 숫자 타입이 아닐 시 이를 숫자로 암묵적 변환시킨다.

  • ‘ ’, [ ], null, false는 0으로 변환
  • true는 1로 변환
  • {}와 undefined는 숫자열로 변환되지 않는다.

3. boolean

falsy한 값들은 모두 false로 암묵적 변환할 수 있다. falsy한 값 외에는 boolean으로 암묵 변환 시 모두 true값으로 바뀐다.

falsy 값: false, undefined, null, 0, -0, NaN, ‘ ’

< 헷갈릴 수 있겠어! >

빈 배열이 숫자열로 변환될 시에는 0으로 전환되고, boolean값으로 전환되면 true값이다! 

명시적 타입 변환

1. 문자열 타입으로 변환하기

  • String(5) //'5' :: 숫자, 불리언 대상으로 가능
  • (5).toString() //'5' :: 숫자, 불리언 대상으로 가능
  • 5 + ‘ ’ //'5':: 숫자, 불리언 대상으로 가능

2. 숫자 타입으로 변환하기

  • Number(’5’) //5 :: 문자열, 불리언 대상으로 가능
  • parseInt(’5’), parseFloat(’5’) //5 :: 문자열 대상으로 가능
  • 단항 산술 연산자: +’0’ → 0 , +true → 1 ::문자열, 불리언 대상으로 가능
  • * 산술 연산자: ‘0’ * 1   0 :: 문자열, 불리언 대상으로 가능

3. boolean으로 변환하기

  • Boolean(’’) // false :: 문자열, 숫자, null, 객체 대상으로 가능
  • !! 활용: !!’x’ → true, !!’’ → false :: 문자열, 숫자, null, 객체 대상으로 가능

단축 평가

단축 평가는 표현식을 평가하는 도중에 평가 결과가 확정된 경우 나머지 평가 과정을 생략하는 것을 뜻한다. 논리곱 연산자(&&)와 논리합(||) 연산자의 특성을 활용하여 표현한다.

true || anything // true 
false || anything // anything
true && anything // anything
false && anything // false

활용법 1. if문 대체

let done = true
let message = ''

if(done) message = '완료'
// done이 true면 '완료' 표출, false면 ''가 표출된다.

message = done || '완료'
// done이 true면 '완료' 표출, false면 ''가 표출된다.

활용법 2. 객체 속성 값이 null 또는 undefined일 때 에러 발생 방지

사용하려는 값이 객체라 생각해서 객체의 속성을 참조했는데 알고보니 값이 객체가 아닌 null이나 undefined 였다면 참조 시 에러가 발생한다. 이를 방지하기 위해 단축 평가를 사용할 수 있다.

let ele = null
console.log(ele && ele.value) 
// && 앞이 falsy값이면 falsy한 값이 그대로 출력된다. true 값이면 뒤의 값이 표현된다.

하지만 단축 평가를 이용하면 좌항 피연산자에서 0이나 ' ' 값을 falsy한 값이 아닌 의미있는 값으로 쓰는 경우에서조차 falsy 취급을 받아 우항 피연산자가 나온다. 

그래서 이보다는 ES11에서 도입된 옵셔널 체이닝을 활용한다면 좀 더 안정적으로 에러를 방지할 수 있다.

옵셔널 체이닝은 ?. 붙여서 사용하는 것으로, 대상 변수가 null이나 undefined인 경우 undefined를 반환하고 그 외의 값은 참조를 이어간다.

//단축 평가를 사용함으로써 나오는 문제점
let str = ''
let length = str && str.length
console.log(length) // ''
/* '' -> str가 없으면 0이 뜨고, 있으면 해당 문자열의 길이가 나오길 바랬는데뜨길 바랬는데 
* falsy값으로 인해 '' 값이 반환되었다.
*/

// 옵셔널 체이닝
let ele = null
console.log(ele?.value) // undefined

 

활용법 3. 함수 매개변수 기본값 설정

함수 호출 시 인수를 전달하지 않으면 매개변수에는 undefined가 할당된다. 이 때 단축평가를 활용하여 매개변수의 기본값을 설정하면 에러를 방지할 수 있다.

function test(str){
	str = str || ''
	return str.length
}
test() // 0

하지만 단축 평가를 이용하면 좌항 피연산자에서 0이나 ' ' 값을 falsy한 값이 아닌 의미있는 값으로 쓰는 경우에서조차 falsy 취급을 받아 우항 피연산자가 나온다. 

그래서 이보다는 ES11에서 도입된 null 병합 연산자를 활용한다면 좀 더 의도에 맞게끔 활용할 수 있다.

null 병합 연산자는 ??로 표현하며, ??의 좌항 피연산자가 null 또는 undefined면 우항의 피연산자 반환되고, 그렇지 않으면 좌항의 피연산자를 반환한다.

let test = null ?? 'default'
console.log(test) //default

혹은 ES6의 매개변수 기본값 설정을 통해 할 수도 있다.

function test(str = ''){ 
	return str.length
}
test() // ''

 

 

 

Comments