33. JavaScript 다시보기 (2)

JSLEE·2024년 6월 11일

Flow Control

사용자는 컴퓨터에게 명령을 하고, 컴퓨터는 수행한다.
이 과정을 flow라고 하고, 이것을 제어하는 것을 flow control이라고 생각하면 될 것 같다.

제어흐름의 종류

  • goto : 다른 구문에서 시작 -> 권장 x
  • choice : 일부 조건이 충족되는 경우, 명령문 실행 -> if-else, switch
  • loop : 조건이 충족될 때까지 명령문을 실행 -> collection loop, general loop
  • continue : 현재 실행 구문에서 떨어진 구문을 실행 -> loop continuation
  • break : 프로그램 실행을 중단 -> loop early exit, 함수 실행 정지

expression / statement

  • 표현식(expression) : 유효한 코드 단위

표현식 평가 -> 새로운 값을 생성 OR 기존 값을 참조
리터럴 표현식 : const a = "a"
함수 표현식 : const fun = function(){}

  • 문 (statement) : 프로그램을 구성하는 최소 실행 단위

ex)
변수 선언문 : let a ;
할당문 : a = "a"
함수선언문 : function 함수() {}
조건문 : if (true){}

블럭문 : { }
명령문들을 그룹으로 묶을 수 있는 블럭문
한 쌍의 중괄호로 묶어 표현

제어문 :
choice : if-else , switch
loop early exit : break
loop continuation : continue
subroutine exit : return
non-local control flow : try-catch , throw, generator, async

반복문 :
conditinal loop : while, do..while
general loop : for
collection loop : for...in , for...of

조건문

조건문 : 일부 조건이 충족되는 경우에만 명령문을 수행한다.
if-else , switch 이 있다.

조건문에서, false, undefined, null, 0 , NaN, "" 은 모두 False의 값으로 평가된다.

또한, 조건문을 중첩해서 사용하면 가독성이 떨어지고 이해하기 어려워지므로,
return 등을 이용하여 guard clauses 형태로 구현한다.

반복문

while문 :
시작할때 조건을 평가 : while( ) { } - 본문이 실행되기 전, 조건을 평가한다.
마지막에 조건을 평가 : do { } while( ) - 본문이 실행된 후에, 조건을 평가한다.

for문 :
for(초기화 ; 조건식 ; 증감문;) 형태
ex)

for( let i = 0 ; i < 10 ; i++ ) {}

collection loop (Foreach):
for문과 다르게, 루프변수(카운터 ex. i )를 관리하지 않는다.
코드가 더 단순해질 수 있다.
for of, for in 등이 있다.

제어문

break문 : 프로그램 실행의 중단 기능을 수행한다.
가장 가까운 반복문, switch문을 종료시킨다.

continue문 : 현재 반복을 종료하고 (전체 루프를 종료시키는 게 아님), 다음 loop를 실행한다.

예외(Exception)

Exception : 런타임 때 발생할 수 있는 의도치 않은 상황

여기서 핸들링(handling)은 대응한다는 의미를 가지고,
컨트롤(control)은 예외를 예상하고 처리를 한다는 의미를 가진다.

즉, 개발자는 예외 상황을 핸들링하고 컨트롤해야한다.

예외의 원인은 주로 다음과 같다.

  • 코드 레벨
  • 하드웨어, 디바이스
  • 라이브러리 문제
  • 사용자 입력 실수

코드레벨에서 발생하는 Exception :
ECMAScript Error : 자바스크립트에서 발생하는 에러타입 - RangeError , ReferenceError, SyntaxError, TypeError 등
DOMException : Web API 에서 발생하는 에러타입 - NetworkError, AbortError, TimeoutError 등

그 외의 예외 :
개발자도 예상하지 못한 예외 상황에 대해서는, Error객체를 사용하여 직접 에러를 정의(new Error())하고 발생(throw)시킨다.

throw와 error 객체

throw : 예외를 발생시킬 때 사용한다. catch블럭에서, 발생한 에러를 핸들링한다.
throw가 실행되면, 에러 객체와 함께 에러가 throw되고, 현재 블럭의 실행이 중단되며, catch 블록으로 이동한다.
catch블록이 없으면 프로그램을 종료한다.

Error 객체 : Error객체를 정의하여 사용 가능하다.
사용방법 : new Error("에러 메시지")
속성 :
Error.message
Error.name

ex)

const customError = new Error("customError")
customError.message = "에러메시지"
customError.name = "에러이름"

try ...catch

try-catch는 이전 포스트에서 공부하였었다.
try-catch를 통해 Error가 발생했을 때, 에러를 핸들링한다.

객체란?

객체 : 속성을 가진 독립적인 개체 ( = 속성으로 구성된 집합 )
객체는 키와 값을 가진다. (key-value)

값을 사용할 땐, 다음의 2가지 방법을 사용할 수 있다.

  • 마침표 표기법 : object.property
  • 대괄호 표기법 : object["property"]

메서드 : 객체에 속해있는 함수이다. 다음의 방법으로 정의가 가능하다.

const obj = {
	property1 : function() {
	console.log("1")
	}

	property2() {
	console.log("2")
	}
}
obj.property1( ) ; 
obj.property2( ) ;

객체의 생성 방법 3가지

  1. 리터럴 표기 : const foo = { name : 'apple' }
  2. 생성자 함수 이용 : 생성자 함수는 항상 대문자로 시작해야함
function Person (name, age) {
  this.name = name ; 
  this.age = age ;
}
let a = new String()  //  인스턴스 생성
let b = new Person()  //  인스턴스 생성
  1. Object.create 이용 :
const Person = {
  name : "Lee", 
  age : 25,
  getName : function() {}
}

const Lee = Object.create(Person) ; 

객체의 특징 :

  • 객체는 원시타입과 다르게 값의 변경이 가능하다. (mutable)
  • 객체는 참조형태로 전달된다.

객체 속성(properties) 나열 방법 :

  1. for...in 사용

  2. Object.keys(객체) : 열거 가능한 속성 이름을 배열로 반환

  3. Object.getOwnPropertyNames(객체) : 모든 속성 이름을 배열로 반환

ex)

const parent = {
	age : 55,
	gender : 'male'
}
function Child(name) {
	this.name = name ; 
}

Child.prototype = parent ; 
const child = new Child('Kim') ;

Object.keys(child) // ['name']
Object.getOwnPropertyNames(child) // ['name']
for ( Const key in child ) {
	console.log(key); 
} // name , age, gender

속성을 삭제하는 방법 - delete

delete 속성이름

delete는 반환값으로 true(성공), false(실패)을 반환한다.
데이터 처리 - 객체와 빌트인 객체 : 객체간 비교와 복사

객체의 비교와 복사

객체는 참조타입이므로, 객체를 비교 및 복사할 때 고려해야할 사항이 있다.

속성이 같지만, 다른 메모리를 참조하는 객체를 서로 비교하면, false가 나온다. 다음의 예시를 보자.

ex)

let foo = {
	name = "lee"
}
let bar = {
	name = "lee"
}
console.log( foo === bar ) // false
console.log( foo === foo ) // true

또한, 동일한 객체를 생성하고 싶을 때, 단순히 다른 변수에 객체를 할당하게 되면 동일한 메모리주소가 할당된다.

let a = {
	name : "lee"
}

let b = a

b.name = "kim"
console.log(a.name)  // kim

따라서, 객체의 값을 복사해서 사용하고 싶을 때에는, 얕은 복사깊은 복사를 사용한다.

얕은 복사 : 복사된 객체의 속성 중 한 개 이상 같은 참조를 하고 있을 때 사용한다.
방법 : Object.assign({ }, 객체) 또는 { ...객체 }
얕은 복사의 경우, 객체안의 객체(중첩된 객체 - Nested Object)의 경우에는 같은 메모리를 참조하므로 주의해야 한다.

ex)

let person = {
name : " ",
address : { country : "Korea" }
}
let a = Object.assign({ }, person)
let b = {...person}

a.name = "kim" // 
b.name = "park" // a.name = "kim", b.name = "park"

a.address.country = "Japan" //  a.address.country = "Japan" , b.address.country = "Japan"

깊은 복사 : 복사된 객체의 속석 중 같은 참조를 하고있는 속성이 아예 없을 때 사용한다.

방법 :

  • 재귀함수 이용 ( lodash 라이브러리 - cloneDeep )
  • JSON.stringify 이용 (객체 -> 문자열변환(참조 끊어짐) ->객체)

자바스크립트 객체의 분류 :

  • ECMAScirpt의 표준 빌트인 객체
  • 호스트 객체 : DOM API

ECMAScirpt의 표준 빌트인 객체 :
기초 객체 : Object, Function , Boolean , Symbol
오류 객체 : Error
숫자 및 날짜 : Number, BigInt, Math, Date
텍스트 처리 : Regex(정규표현식), String(문자열)
Collection : Array(index기반), Map, Set (Key 기반) 등
구조화된 데이터 객체 : JSON


Regex(Regular expression) - 정규표현식

정규표현식은, 문자열에서 특정 문자 조합을 찾기 위한 패턴이다. 정규식이라고도 부른다.

형태는 다음과 같다.
/pattern/flags
ex)

/\w+\s/g

pattern 부분은, 단순패턴과 특수문자(assertion, 문자클래스, 그룹과 범위, 수량자, 유니코드 속성 이스케이프)를 사용할 수 있다.

flag부분에는 flag속성값을 작성한다.

정규표현식 생성방법 :

  1. 리터럴표기법 :
    평가할때 정규 표현식을 컴파일한다.
    정규식이 변하지 않을 때 사용한다.
    형태 : /pattern/flag

  2. RegExp 객체 :
    런타임 때 컴파일된다.
    패턴이 변할 가능성이 있을때, 알수없는 데이터에서 정규식을 가져올 때 사용한다.
    형태 : new RegExp(/pattern/, flag)

RegExp 객체는, String의 메소드인 match, matchAll, search, replace, replaceAll, split 등을 사용할 수 있다.


collection이란?

collection이란, 데이터 항목들의 그룹을 의미한다.
프로그래밍에서는 전반적으로 list, set, tree, graph 등이 있고,
자바스크립트에서는 indexed collection, keyed collection이 존재한다.

indexed collection : index값을 기준으로 정렬된 데이터 집합을 의미한다. - Array, TypedArray
keyed collection : Key값을 기준으로 정렬된 데이터 집합을 의미한다. - Map, Set

indexed collection - Array :
new Array(arrayLength) 를 통해 길이가 지정된 빈 배열 만들 수 있다.
new Array(val1, val2) 를 통해 요소가 지정된 배열을 만들 수 있다.

자바스크립트는 배열을 Object처럼 사용하여,
index값을 속성(property)이름으로 사용하고,
그에 매핑되는 값을 이용하는 key-value처럼 사용한다.

keyed collection - Map, WeakMap

Map은 Key와 Value가 매핑되어있다.

const foo = new Map() ;
foo.set(key, value) ;

이 때, Key는 유니크한 값을 가진다.

Map과 Object의 차이

Map :
모든 값을 키로 활용 가능하다.
기본 속성들이 없으므로, default 속성과의 충돌이 발생할 일이 없다.
size 인스턴스 속성으로 객체의 크기를 얻을 수 있다.
Map은 추가된 순서대로 반복된다.
Map은 iterable이 가능하다. (forEach 사용 가능)
키,값의 추가/제거에 성능이 좋다.
직렬화, 구문분석을 제공하지 않는다.

Object :
string, Symbol 데이터 타입만 속성과 데이터로 가질 수 있다.
Object prototype의 기본속성과 동일한 키를 생성할 때 충돌이 발생한다.
객체의 크기는 수동으로 추적해야 한다.
순서의 보장이 안된다.
iterable이 불가능하다.
키,값의 추가 및 제거에 성능이 좋지 않다.
직렬화, 구문분석을 제공한다. (JSON.stringfy, JSON.parse)

map은 getset을 이용하여 데이터에 접근하고, 변경한다.

WeakMap : 키에 대한 강력한 참조를 생성하지 않는 map 자료형이다.
키는 object만을 허용하고, 객체 정보를 노출하지 않는다.
따라서, 객체의 사적인 정보를 저장하거나, 상세 구현내용을 숨기기 위해 사용한다.

keyed collection - Set, WeakSet

Set : 모든 값들의 집합
입력된 순서에 따라 요소의 반복처리가 가능하다. 즉, for...of 를 통해 순회가 가능하다.
배열->Set / Set-> 배열로 변환이 가능하다.

배열의 경우에는 indexOf를 사용하여 값의 포함 여부를 확인하는데, 퍼포먼스가 느리고,
Set의 has method가 퍼포먼스가 더 좋음.

또한, 배열은 요소를 제거할 때 배열을 잘라내고 이동시켜야한다. ( 배열의 요소를 삭제하면, 뒤의 요소들을 옮기는 과정 필요)
Set은 delete method를 이용해 키를 바로 삭제가 가능하다.

요소를 찾을 때에도,
배열은 NaN을 indexOf로 확인 불가능하고,
Set은 NaN의 포함여부를 확인 가능하다.

WeakSet : 객체 컬렉션. 인자로 object값만을 허용한다.

JSON 객체

다양한 환경 간에 데이터를 주고 받기 위해 직렬화 작업이 필요한데,
JSON은 직렬화를 지원한다.

직렬화(serialization) : 문자열로 변환하는 것 -> JSON.stringfy()
역직렬화(deserialization) : Object로 변환하는 것 -> JSON.parse()

profile
공부한 내용들을 정리하기 위해 사용하는 블로그입니다.

0개의 댓글