TIR: 리액트 딥다이브 (1) 자바스크립트

Lumpen·2024년 8월 25일
0

TIL

목록 보기
243/244

리액트에서의 동등 비교

자바스크립트의 동등 비교는 ==, ===, Object.is 다
Object.is 는 ES6 문법이기 떄문에 리액트에서는 Polyfill 을 함께 사용한다

Object.is()

Object.is() 는 두 개의 인수를 받아 동일한지 비교 후 반환하는 메서드로
비교하기 위해 하는 형변환을 하지 않는다
그렇지만 === (일치 연산자) 와는 다르게 조금 더 정교한 비교를 한다
-0 === +0 // true
Object.is(-0, +0) // false

Number.NaN === NaN // false
Object.is(Number.NaN, NaN) // true

NaN === 0/0 // false
Object.is(NaN, 0/0) // true

위와 같이 조금 더 개발자가 원하는 비교를 위해 내부적인 알고리즘이 동작한다
하지만 객체 비교는 얕은 비교를 한다

is()

런타임에 Object.is() 가 있으면 사용하고 아니라면 is() 를 사용한다
Object.is 는 익스플로러 등에 존재하지 않기 때문에 폴리필을 넣어준 것으로 보인다

function is(x: any, y: any) {
	return (
    	(x == y && (x !== 0 || 1/x === 1/y)) || (x !== x && y !== y) 
    )
}

objectIs()

objectIs 변수에는 Object.is() 또는 is() 함수가 들어간다

const objectIs: (x: any, y: any) => boolean =
      typeof Object.is === 'function' ? Object.is : is

export default objectIs

리액트에서는 objectIs() 를 기반으로 동등 비교를 하는
shallowEqual() 함수를 만들어 사용한다
의존성 비교 등 리액트의 동등 비교가 필요한 다양한 곳에서 사용된다

shallowEqual() - 리액트의 비교 함수

shallowEqual() 의 내부 동작은
objectIs() 과 hasOwnProperty() 를 함께 사용하여
객체 간 비교도 추가되어 있다
다만 객체의 1뎁스만 비교하도록 구현되어 있다
객체의 크기는 무한정 될 수 있고
모든 비교를 재귀함수로 구현하면 성능상 이슈가 있을 것이기 때문에
1뎁스 까지만을 비교하는 것 같다
또한 기본적인 기능에서는 1뎁스 비교만 하면 충분하다
props 가 객체로 전달되기 때문에

때문에 리액트 상태관리 시 객체타입의 데이터를 다루게 될 경우 주의해야 한다
-> 필요한 곳에 깊은 비교 구현
또한 props 는 객체이기 때문에
props 의 값에 객체를 사용하는 경우 더욱 주의해야 하겠다

falsy 값

  • false
  • 0, -0, 0n, 0x0n
  • NaN
  • ''
  • null
  • undefined

빈 객체와 빈 배열은 truthy 값이므로 유의해야 한다

빈 객체 확인

Object.keys(obj).length === 0

빈 배열 확인

arr.length === 0

데이터 타입

크게 원시 타입과 객체 타입으로 구분할 수 있다
프리미티브 타입과 레퍼런스 타입이라고 표현하기도 함
객체 타입을 참조 타입으로 부르는 것이 괜찮은 것 같다

Number

자바스크립트의 특징 중 하나로 모든 정수와 실수를 Number 하나의 타입으로 사용한다

BigInt

Number 타입의 한계인 숫자 크기를 극복하기 위해 등장

String

자바스크립트의 특징 중 하나로 문자 타입(Character)이 없고 모든 문자 타입을 문자열로 사용한다

구조 분해 할당 (Destructuring assignment)

구조분해 할당 시 기본 값을 지정할 수 있는데
undefined 일 때만 기본 값을 사용하게 된다

객체 구조 분해 할당

객체 구조 분해 할당 시에는 key를 사용하는데
다른 이름으로 다시 할당 가능하다

객체 구조 분해 할당의 경우 ...rest 기능 사용 시
번들링 크기가 많이 커지므로 꼭 필요한지 고려 후
꼭 필요하다면 외부 라이브러리 등의 사용을 고려해보는 것도 좋다

전개 구문 (Spread Syntax)

배열의 전개 구문을 트랜스파일 하면 concat() 을 사용하였다

const arr1 = [1, 2]
const arr2 = [...arr1, 3, 4, 5]

var arr1 = [1, 2]
var arr2 = [].concat(arr1, [3, 4, 5])

객체 전개 구문

객체 전개 구문은 구조 분해 할당과 마찬가지로
...obj 사용 시 속성값 및 설명자 확인, 심벌 체크 등을 위해
트랜스파일된 코드가 매우 커지게 된다
사용하지 않는 편이 좋겠다

함수

함수 선언문

함수 선언으로는 어떠한 값도 표현되지 않으므로 문으로 분류된다

함수 표현식

자바스크립트의 함수는 일급 객체이기 때문에 값처럼 사용할 수 있다
때문에 함수를 변수에 할당할 수 있다
함수 표현식에서 익명 함수를 사용하는 것이 일반적이라고 하나
최근에는 다른 의미의 가독성을 위해 함수 이름을 작성하는 편인 것 같다
표현식에서의 함수 이름은 함수 내부에서만 사용할 수 있는 식별자가 된다

선언문과의 가장 큰 차이는 호이스팅

화살표 함수

간단하게 작성할 수 있지만 기존의 방식들과 차이가 있다

  • constructor 가 없음
  • arguments 가 없음
  • this 바인딩이 부모를 참조함
    셋 다 사용할 일이 없지만 특히 this 는 신입 면접에서 자주 물어보는 주제..

즉시 실행 함수

  • 독자적인 스코프
  • 명시적으로 재사용을 하지 않음을 밝힐 수 있다

클래스

자바스크립트의 클래스는 자바 등 다른 객체지향 언어에서의 클래스와 생김새는 비슷하지만 다르다
자바스크립트는 프로토타입 객체지향과 함수형 프로그래밍이 가능한 멀티 패러다임 언어
자바스크립트의 클래스는 프로토타입의 Syntax Sugar
프로토타입 객체를 익숙한 Class 문법으로 지원하는 것으로
잘 모르는 사람들은 자바스크립트가 객체지향을 지원하지 않는다고 생각하기도 한다

자바스크립트는 왜 프로토타입을 선택했을까

정적 메서드

static 메서드는 객체 레벨에서 평가되기 때문에 객체 내부에 작성되어 있지만
객체와 같은 위치에 있다고 생각할 수 있다
인스턴스를 생성하지 않아도 사용할 수 있는 것으로 보아 이미 메모리에 올라가 있는 것

window.localStorage.getItem()
Math.random() 

클로저

함수와 함수가 선언된 렉시컬 스코프의 조합
렉시컬 스코프는 변하지 않으므로 정적 스코프라고도 한다
자바스크립트의 개념이 아니라 함수형 프로그래밍의 개념이다
함수 내부의 함수가 자신이 선언된 환경을 기억하여
외부 함수의 변수에 접근할 수 있다

스코프는 변수의 유효 범위로
전역 스코프와 함수 스코프가 있다

클로저를 이해하기 위해서는 스코프 체인과 가비지 컬렉터의 작동 방식을 이해하고 있으면 좋다
정보 은닉, 함수 팩토리, 부분 적용 함수, 비동기 작업, 모듈 패턴에 사용된다

리액트에서의 클로저

대표적으로 useState() 로 클로저를 이용해 내부의 최신 값을 확인한다

클로저를 활용할 때는 메모리 누수에 주의해야 한다

이벤트루프와 비동기

리액트의 비동기 렌더링
비동기 코드를 작성한다는 것이

타입스크립트

타입 가드

타입스크립트 사용하는 쪽에서는 최대한 타입을 좁히는 것이 좋다
타입 가드를 사용하면 타입을 좁히는데 도움을 줄 수 있다

instanceof

incetanceof 는 지정한 인스턴스가 특정 클래스의 인스턴스인지 확인할 수 있다

if (e instanceof AxiosError) {}

typeof

typeof 는 특정 요소의 자료형을 확인한다

if (typeof value === 'string') {}

in

개체의 지정한 키가 존재하는지 확인한다

if ('property' in obejct) {}

덕타이핑

타입스크립트 핵심 원칙은 타입 검사가 값의 형태에 초점을 맞춘다는 것
객체의 타입이 클래스 상속, 인터페이스 구현 등으로 결정되는 것이 아니고
필요한 변수와 메서드만 가지고 있다면 해당 타입에 속하도록 인정해준다

Object.key() 타입 가드 함수

function keyOf<T extends Object>(obj: T): Array<keyof T> {
	return Array.from(Object.keys(obj)) as Array<keyof T>
}
profile
떠돌이 생활을 하는. 실업자, 부랑 생활을 하는

0개의 댓글