티스토리 뷰

WEB/JavaScript

[클린코드 For JS] 3. 타입

Harimad 2022. 6. 27. 20:45

🔖TAG 💡eqeq, 💡instanceof, 💡isNaN, 💡null, 💡Primitive, 💡reference, 💡typeof, 💡undefined, 💡타입검사, 💡형변환 📕

출처😌

클린코드 자바스크립트 | Udemy

자료🙄

Git: pocojang/clean-code-js (github.com)


목차

1. 과정 소개 
2. 변수 다루기 
3. 타입 다루기 🚩
    3-1. 타입 검사
    3-2. undefined & null
    3-3. eqeq 줄이기
    3-4. 형변환 주의하기
    3-5. isNaN
4. 경계 다루기
5. 분기 다루기
6. 배열 다루기
7. 객체 다루기
8. 함수 다루기


3. 타입 다루기


3-1. 타입 검사

typeof 는 문자열로 반환하는 연산자 입니다.

const str = '문자열'
const num = 123
const bool = true
const nul = null
const und = undefined
const sym = Symbol('sym')

console.log(typeof str); // string
console.log(typeof num); // number
console.log(typeof bool); // boolean
console.log(typeof nul); // object
console.log(typeof und); // undefined
console.log(typeof sym); // symbol

console.log(typeof (sym)); //symbol  <- typeof를 함수처럼 사용해도 됩니다.

 

타입을 검사할 때 typeof 로 모든걸 커버할 수 있지 않을까? 라는 생각이 드는데요,

그렇지는 않습니다.

 

타입은 2가지로 나눌 수 있습니다.

PRIMITIVE(원시값) vs REFERENCE(객체)

원시값은 불변하다는 특징을 가지고 있습니다.

REFERENCE는 Object로 볼 수 있는데 종류가 다양합니다. (Array, function, Date etc...)

 

function myFunction() {}

typeof myFunction // 'function'

class MyClass {} // Class는 생성자 함수처럼 이루어져 있는 객체를 만들어내는 표본입니다.

typeof MyClass // 'function'

class가 function으로 나오는 걸 보니 typeof가 많은 걸 인용할 수 없다는 것을 알 수 있습니다.

 

Wrapper 객체를 사용할 때는 Object로 나옵니다.

const str = new String('문자열')

typeof str //'object'

 

이처럼 PRIMITIVE 자료형은 원하는 대로 잘 나오는걸 볼 수 있습니다.

그러나 REFERENCE 값은 typeof로 감별해내기가 어려울 수 있습니다.

결론은 typeof가 타입을 알아볼 수 있는 만능이 아니라는걸 알아야 합니다.

 

치명적인 오류 중에 하나는 null 타입을 볼 때가 있습니다.

typeof null // 'object'

 

PRIMITIVE vs REFERENCE 를 감별해 내기 어려운 경우가 또 있습니다.

JS는 동적으로 변하는 언어이기 때문에 타입 까지 동적입니다.

그 중 하나가 instanceof 연산자가 있습니다.

 

instanceof 연산자는 객체의 프로토타입 체인을 검사하는 기능을 가지고 있습니다.

function Person(name, age) {
    this.name = name
    this.age = age
}

const person1 = new Person('BOB', 10)

person1 instanceof Person // true


const person2 = {
    name: 'BOB',
    age: 10
}

person2 instanceof Person // false


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

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

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

// 결국 REFERENCE 타입의 최상위 타입은 Object 입니다.
// 프로토타입 체인을 타다보면 Array -> Object, Function -> Object, Data -> Object 로 가게됩니다.
// 그래서 instanceof로도 타입검사가 어려움이 있습니다.

 

타입을 검사하는 3번째 방법은 아래와 같습니다.

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

Wraper 객체까지 감지해 낼 수 있습니다.

 

Object // ƒ Object() { [native code] }

Object.prototype
// constructor: ƒ Object()
// hasOwnProperty: ƒ hasOwnProperty()
// isPrototypeOf: ƒ isPrototypeOf()
// propertyIsEnumerable: ƒ propertyIsEnumerable()
// toLocaleString: ƒ toLocaleString()
// toString: ƒ toString()
// valueOf: ƒ valueOf()
// __defineGetter__: ƒ __defineGetter__()
// __defineSetter__: ƒ __defineSetter__()
// __lookupGetter__: ƒ __lookupGetter__()
// __lookupSetter__: ƒ __lookupSetter__()
// __proto__: (...)
// get __proto__: ƒ __proto__()
// set __proto__: ƒ __proto__()


Object.prototype.toString // ƒ toString() { [native code] }


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


//Wraper 객체까지 감지해 낼 수 있습니다.
Object.prototype.toString.call('') // [object String]'
Object.prototype.toString.call(new String('')) //'[object String]'
Object.prototype.toString.call( [] ) //'[object Array]'
Object.prototype.toString.call( {} ) //'[object Object]'
Object.prototype.toString.call( function(){} ) //'[object Function]'
Object.prototype.toString.call( null) //'[object Null]'
Object.prototype.toString.call( new Date() ) //'[object Date]'

 

요약

 

1. JS언어는 동적인 타입을 가지는 언어입니다. 그래서 타입검사가 어렵습니다.

  하나하나 잘 찾아서 타입을 알아봐야 정확하게 알 수 있습니다. (스택오버플로우 참고)

  그러나, 일일이 타입을 외우지 말아야 합니다(낭비)!

2. Primitive vs Reference 타입을 잘 구분해야 합니다.

  typeof 가 타입을 구분짓는 무적은 아닙니다. 타입 구분에 instanceof도 쓰입니다.

 

 

 

3-2. undefined & null

meme1

Some specific values portrayed by toilet papers

 

!null // true
!!null // false

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

// null은 수학연산에서 0으로 취급됩니다.
null + 123 // 123


// undefined는 아무것도 선언하지 않은 기본값이라고 생각하면 됩니다.
// 아래는 선언했지만 값은 정의되지 않았습니다.
let empty;

empty // undefined
typeof empty // 'undefined'

// undefined는 수학연산에서 값으로 쓰이지 않습니다.
undefined + 123 // NaN

!undefined // true

undefined == null // true

undefined === null // false

!undefined === !null // true

// 결국 undefined와 null을 사용할 때 자신만의 컨벤션을 만들어 가는게 중요합니다.

 

요약

1. undefined, null은 값이 없거나 정의되지 않은 것입니다.

  '값이 없다'는건 명시적인 표현을 말합니다.

 

2. null은 숫자적으로 표현할 때 0에 가깝다고 볼 수 있고, typeof null은 'Object' (대표적 오류)가 나옵니다.

  undefined는 숫자적으로 NaN이고, typeof undefined는 'undefined'가 나옵니다.

 

3. undefined와 null을 사용할 때는 조심성을 가지고 써야합니다.

 

 

3-3. eqeq 줄이기

eqeq는 JS에서 동등 연산자를 의미합니다.

 

JavaScript 동등성 테이블 게임 (eqeq.js.org)

 

JavaScript Equality Table Game

Find out how well you know (or don't know) the JavaScript == operator rules

eqeq.js.org

 

동등연산자 '=='를 쓰면 형변환(type casing)이 일어납니다.

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

// 엄격 동등 연산자
'1' === 1 // false

만약 어떤 값이 있는데

숫자 0 과 같은지 확인 할 때는, 직접 형변환을 해서 비교하길 추천합니다.

내가 동등 연산자를 잘 활용할 줄 안다고해서 자주 사용하면 절대 좋은것이 아닙니다.

오히려 동료들에게 혼란만 줄 뿐입니다.

그러니 동등 연산자('==')의 사용을 지양하시고 엄격 동등 연산자('===')를 사용하시면 좋겠습니다.

const ticketNum = {
	value: 0,
}

ticketNum.value == 0 // true
Number(ticketNum.value) === 0 // true

참고 : eqeqeq - ESLint - Pluggable JavaScript Linter

 

3-4. 형변환 주의하기

암묵적인 형변환 VS 명시적인 형변환

 

① 암묵적인 형변환

동등 연산자('==')는 형 변환을 일으켜 느슨한 검사를 하는 연산자 입니다.

이렇게 형 변환을 자동으로 시켜주는 것을 '암묵적인 형변환'이라고 합니다.

따라서 아래의  검사가 다 유효합니다.

'1' == 1 // true
1 == true // true
0 == false // true

'암묵적인 형변환'에 대해서 조금 더 보겠습니다.

11 + ' 문자와 결합' // '11 문자와 결합'

!!'문자열' // true

!!'' // false

 

② 명시적인 형변환

사용자가 의도적으로 형변환을 시켜주는 것을 말합니다.

형변환을 할 때는 명시적으로 하는게 바람직합니다.

String(11 + ' 문자와 결합') // '11 문자와 결합'
Boolean('문자열') // true
Boolean('') // false
Number('11') // 11

parseInt('9.9999', 10) // 9

parseInt 같은 경우에 많은 분들이 헤깔릴 수 있습니다.

두 번째 인자는 꼭 넣어주는게 좋습니다. 두 번째 인자가 없을 땐 기본적으로 10진수로 계산 되지 않습니다.

예를 들어, 0x로 시작하면 16진법으로 처리합니다.

parseInt('0x100') // 256

참고: JS / 함수 / parseFloat(), parseInt() – 문자열을 수로 바꾸는 함수

 

JavaScript / 함수 / parseFloat(), parseInt() - 문자열을 수로 바꾸는 함수

parseFloat() parseFloat()는 문자열을 실수로 바꾸는 함수입니다. 문법 parseFloat( string ) 수로 시작할 때 그 수를 실수로 바꿉니다. 띄어 쓰기로 여러 개의 수가 있으면 첫번째 수만 바꿉니다. 공백으로

www.codingfactory.net

 

요약

명시적인 형변환: 사용자가 형변환 할 때

암묵적인 형변환JS가 평가해서 형변환 할 때

 

📌사람이 명시적으로 형변환을 시켜서 예측가능한 코드를 작성하는 것이 좋습니다.

 

3-5. isNaN

IEEE 754 - 위키백과, 우리 모두의 백과사전 (wikipedia.org)

 

사람이 생각하는 수는 10진수이고

컴퓨터가 생각하는 수는 2진수 입니다.

이러한 숫자의 인식차이 때문에 간극이 생기는데, 대표적인 예시가 소수점을 나타낼 때 입니다.

컴퓨터는 이 부동소수점을 나타낼때 IEEE 754 표준을 이용합니다.

Number.MAX_SAFE_INTEGER // 9007199254740991
Number.isInteger // ƒ isInteger() { [native code] }

 

isNaN으로 해당 요소가 숫자인지 판단하는것엔 문제가 많습니다.

// is Not A Number => 숫자가 아니다
isNaN(123) // false -> 숫자가 숫자가 아니다 (숫자가 맞다) <- 혼동

그래서 해당 요소가 숫자가 맞는지 판단할 때는, Number.isNaN(요소)로 검사하면 좋습니다.

// ES2015 이전
isNaN(123 + '테스트') // true

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

isNaN // 느슨한 검사
Number.isNaN // 엄격한 검사
 
 
 
댓글
다크모드
Document description javascript psychology
더보기 ,제목1 태그 호버