You Don't Know JS - 1.타입과 문법 - 1.타입
[ You Don’t Know JS 정리 ]
1. 타입
1.1 타입, 그 실체를 이해하자
1.2 내장 타입
1.3 값은 타입을 가진다
1.3.1 값이 없는 vs 선언되지 않은
1.3.2 선언되지 않은 변수
1.1 타입, 그 실체를 이해하자
타입 : 자바스크립트 엔진, 개발자 모두에게 어떤 값을 다른 값과 분별할 수 있는, 고유한 내부 특성의 집합
거의 모든 자바스크립트 프로그램에서 강제 변환이 일어나므로 타입을 확실하게 인지하고 사용하는 것이 중요
1.2 내장 타입
7가지 내장 타입 (es6 기준)
- null : primitive type
- undefined : primitive type
- boolean : primitive type
- number : primitive type
- string : primitive type
- object : reference type
- symbol : primitive type
값 타입은
typeof연산자로 알 수 있다.1
2
3
4
5typeof undefined === "undefined"; // true
typeof true === "boolean"; // true
typeof 42 === "number" // true
typeof {life : 42} === "object" // true
typeof Symbol() === "symbol" // true
하지만 내장 타입과 1:1로 정확하게 매치되지는 않는다.
1 | typeof null === "object" // true |
null은 ‘falsy’한 유일한 원시 값이지만, 타입은 ‘object’인 특별한 존재다.
그래서 타입으로 null 값을 정확히 확인하려면 조건이 하나 더 필요하다.
1 | var a = null; |
typeof가 반환하는 문자열은 하나 더 있다.
1 | typeof function a(){...} === "function" // true |
마치 function이 최상위 레벨의 내장 타입처럼 보이지만 실제로는 ‘object’의 하위 타입이다. => 호출 가능한 객체
따라서 함수에 프로퍼티를 둘 수 있고, 함수에 선언된 인자 개수는 함수 객체의 length 프로퍼티로 알 수 있다.
1 | function a(a,b) { |
1.3 값은 타입을 가진다.
- 값에는 타입이 있지만, 변수에는 타입이란 없다.
- 자바스크립트는 타입 강제를 하지 않는다. 변수값이 처음에 할당된 값과 동일한 타입일 필요 없다.
typeof의 연산자의 반환 값은 언제나 문자열이다. ex) “string”, “number”
1.3.1 값이 없는 vs 선언되지 않은
- “undefined”(값이 없는)과 “undeclared”(선언되지 않은)을 동의어처럼 생각하기 쉬운데 둘은 완전히 다른 개념
- undefined : 접근 가능한 스코프에 변수가 선언되었으나 현재 아무런 값도 할당되지 않은 상태를 가리킨다
- undeclared : 접근 가능한 스코프에 변수 자체가 선언조차 되지 않은 상태
1
2
3var a;
a; // undefined
b; // ReferenceError : b is not defined
1.3.2 선언되지 않은 변수
여러 스크립트 파일의 변수들이 전역 네임스페이스를 공유할 때,
typeof가 유용typeof로 전역 변수 체크프로그램의 ‘디버그 모드’를
DEBUG라는 전역 변수로 조정한다고 쳤을 때콘솔 창에 메시지 로깅 등 디버깅 작업을 수행하기 전, 이 변수의 선언 여부를 체크
최상위 전역 스코프에
var DEBUG = true라고 ‘debug.js’ 파일에만 선언하고, 개발/테스트 단계에서 이 파일을 브라우저가 로깅하기만 하면 된다.그러나 나머지 어플리케이션 코드에서 ReferenceError가 나지 않게 하려면 조심해서
DEBUG전역 변수를 체크해야 한다.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[utility.js]
function sum(a,b) {
return a + b;
}
function product(a,b) {
return a * b;
}
export {product, sum};
[app.js]
import {product, sum} from 'utility';
console.log(product(1,2)) //2
console.log(sum(1,2)) //3
// 에러 발생
if (DEBUG) {
console.log("디버깅 시작")
}
// 안전하게 존재 여부 체크
if (typeof DEBUG !== "undefined") {
console.log("디버깅 시작")
}
typeof없이 전역 변수를 체크하는 다른 방법전역 변수가 모두 전역 객체(브라우저는 window)의 프로퍼티라는 점을 이용하는 것
1
2
3if (window.DEBUG) {
// ...
}하지만 가급적 삼가는 것이 좋다.
- 전역 변수를 꼭 window 객체로만 호출하지 않는 다중 자바스크립트 환경(브라우저뿐만 아니라 서버에서 실행되는 node.js)이라면 더욱
전역 변수를 사용하지 않을 때
일부 개발자들은 이런 설계 방식이 그다지 바람직하지 않다고 말한다.
ex) 다른 개발자가 유틸리티 함수를 자신의 모듈/프로그램에 카피 앤 페이스트하여 사용하는데, 가져다 쓰는 프로그램에 유틸리티의 특정 변숫값이 정의되어 있는지 체크해야하는 상황
1
2
3
4
5
6
7
8function doSomethingCool() {
var helper =
(typeof FeatureXYZ !== "undefined") ?
FeatureXYZ :
function() { /*기본 XYZ 기능*/};
var val = helper();
}doSomethingCool함수는FeatureXYZ변수가 있으면 그대로 사용하고, 없으면 함수 바디를 정의한다.이렇게 해야 다른 사람이 카피 앤 페이스트를 해도 안전하게
FeatureXYZ가 존재하는지 체크할 수 있다.
의존성 주입 설계 패턴
- 명시적으로 의존 관계를 전달
1
2
3
4
5
6function doSomethingCool(FeatureXYZ) {
var helper = FeatureXYZ ||
function() {/*기본 XYZ 기능*/};
var val = helper();
}
- 명시적으로 의존 관계를 전달