[클린 코드 JS] 타입/경계 다루기

yoon Y·2022년 10월 15일
0

클린 코드

목록 보기
3/3

타입 검사

typeof

  • 반환값은 string
  • 원시타입을 주로 검사
  • 함수처럼 사용할 수도 있다. typeof ('문자열')

js에서 타입검사할 때 주의해야하는 이유

  1. 참조타입은 typeof로 판별해내기 어렵다.
  2. null은 object로 나온다 → 오류임
  3. object생성자로 만든 값들은 거의 object로 찍힌다.
  4. js는 동적으로 변하는 언어, 타입까지 동적으로 변하기 때문에 주의해야 한다.
typeof '문자열'     // 'string'
typeof  true      // 'boolean'
typeof  undefined // 'undefined'
typeof  123       // 'number'
typeof  Symbol    // 'symbol'
  

instanceof

객체의 프로토타입 체인을 검사하는 것, 참조타입을 주로 검사한다.
생성자 함수로 만든 객체의 부모 생성자를 확인하는 것.

const arr = []
const func = function() {}
const date = new Date()

arr instanceof Array     // true
func instanceof Function // true
date instanceof Date     // true

문제점
프로토타입 체인을 타기 때문에 최상위 생성자인 Object를 해도 true가 나온다.

arr instanceof Object     // true
func instanceof Object // true
date instanceof Object     // true

해결책

Object.prototype.toString.call(date) // '[object date]'

undefined vs null

null

  • 명시적으로 값을 없음을 나타낸다.
  • 산술 연산을 했을 때 0으로 취급된다.
  • type이 object이다.
let varb= null;

typeof varb // 'object'

null의 혼란함

!null   // true
!!null  // false

null === false  // false

!null === true  // ture

undefined

  • 변수를 선언만 하고 값을 할당하지 않았을 때의 기본값이다.
  • 0으로 취급되지 않는다.(NaN) - 산술할 수 없다.
  • type이 undefined이다.
let varb= null;

typeof varb // 'undefined'

매우 혼란하기 때문에 팀에서 컨벤션으로 어떤 것을 쓸지 정하는 것이 좋다.

undefined == null    // true
undefined === null   // false
!undefined === !null // true

eqeq(동등 연산자) 줄이기

동등 연산자 사용 시 암묵적인 형 변환이 일어난다 - type casting

'1' == 1  // true
1 == true // true

어떻게든 명시적으로 형변환을 해서 일치 연산자(값+타입까지)로 비교하는 것이 좋다.

린트 설정으로 강제하는 것이 좋다.

연산 시 형 변환 주의하기

타입이 다른 값들 끼리 연산을 해도 암묵적인 형변환이 일어난다.
내장 메소드를 사용해서 명시적으로 형변환하는 것이 좋다.

String(11 + '문자와 결합') // '11 문자와 결합'

Boolean('문자열')         // ture
Boolean('')				// false
Number('11')			// 11

// 2번째 인자로 진수를 설정해주는 것이 좋더.
parseInt('9.9999', 10) // 9

isNaN

애초에 뒤집어진 의미라 헷갈릴 수 있다

isNaN은 느슨한 검사
숫자에 텍스트가 포함되어있으면 숫자가 무시된다.

isNaN(123+'테스트') // true

Number.isNaN은 엄격한 검사
숫자가 포함되어 있으면 텍스트는 무시된다.

Number.isNaN(123+'테스트') // false

Number.isNaN으로 검사하는 게 명확하다.


경계 다루기

어떤 범위를 다루느냐에 따라 사람들이 암묵적으로 생각하는 정해진 네이밍이 있다.
함수가 어떤 범위를 다루는지에 따라 그에 적합한 파라미터 네이밍을 해주면 명시적으로 사용할 수 있다.

min - max

  • 최소값과 최대값을 다룬다.
  • min~max사이의 연속적인 모든 숫자를 다룰 때 사용한다.

예) min: 1, max: 5일 때
이상 이하인 경우 - 1,2,3,4,5
초과 미만인 경우 - 2,3,4

function genRandomNumber(min, max) {
	return Math.floor(Math.random() * (max - min + 1)) + min;
}

// 상수로 정의한 인수를 사용
const MIN_NUMBER = 1;
const MAX_NUMBER = 45;

genRandomNumber(MIN_NUMBER, MAX_NUMBER);

최소값과 최대값 포함 여부 설정
1. 최소값과 최대값 포함 여부를 컨벤션으로 결정한다. (이상-초과 / 이하-미만)
2. 함수를 사용할 때 인자를 미리 상수에 할당해놓고, 네이밍에 최소값과 최대값 포함 여부를 표현한다.

// 초과 미만
const MIN_NUMBER_LIMIT = 1;
const MAX_NUMBER_LIMIT = 45;

// 이상 이하
const MIN_IN_NUMBER = 1;
const MAX_IN_NUMBER_LIMIT = 45;

begin - end

begin - end로 표현할 수 있는 암묵적인 규칙 → 주로 날짜 범위를 정할 때 사용된다.

function reservationDate(beginDate, endDate) {
	// ...some code
}

reservationDate('YYYY-MM-DD', 'YYYY-MM-DD');

first - last

  • 첫, 마지막 사이 값들이 연속적이거나 어떤 규칙이 적용되는 것과 관련이 없을 때 사용한다.
  • 처음과 마지막만 다루고 중간 요소들에 대한 것은 다루지 않는다.
    ex) 돔 메소드 firstChild, lastChild
const students = ['포코', '존', '현석'];

function getStudents(first, last) {
	// ...some code
}

getStudents(students[0], students[students.length-1])

매개변수의 순서가 경계다

  • 호출하는 당시의 함수의 네이밍과 인자의 순서의 연관성을 고려한다.
  • 매개변수는 2개를 넘지 않는게 좋다.
    매개변수가 2개 일 때는 시작과 끝이 있어서 함수 이름과 연관 지어 다양한 관계들을(대립, 평등…) 유추할 수 있기 때문이다.

인자가 2개 초과로 많아질 경우

  • 규칙적이지 않고 갯수가 정해지지 않은 매개변수들 → argument, rest parameter사용
  • 들어올 값이 정해져 있지만 수가 많고 순서가 상관 없는 경우 → 객체에 담아서 넘긴다.
  • 이미 만들어져 있는 함수를 수정할 수 없을 때 → 함수로 래핑한다.
// someFunc 에서 someArg1, someArg3을 많이 쓰는 경우

function someFunc(someArg1, someArg2, someArg3, someArg4) {
  // ...some code
}

function getFunc(someArg1, someArg3) {
	someFunc(someArg1, undefined, someArg3)
}
profile
#프론트엔드

0개의 댓글