function은 최상위 레벨의 내장 타입이 아니라 object의 하위 타입이다. (호출 가능한 객체 - 내부 프로퍼티 [Call]로 호출할 수 있는 객체)
배열은 숫자 인덱스를 가지며, length 프로퍼티가 자동으로 관리되는 등의 특성을 지닌, 객체의 하위 타입이다.
값은 타입을 가진다
값에는 타입이 있지만, 변수엔 따로 타입이란 없다. 변수는 언제라도, 어떤 형태의 값이라도 가질 수 있다.
자바스크립트는 타입강제를 하지 않는다. 변숫값이 처음에 할당된 값과 동일한 타입일 필요가 없다.
undefined vs undeclared
undefined와 undeclared를 동의어처럼 생각하기 쉽지만, 자바스크립트에서 둘은 완전히 다른 개념이다.
undefined : 접근 가능한 스코프에 변수가 선언되었으나 현재 아무런 값도 할당되지 않은 상태
undeclared : 접근 가능한 스코프에 변수 자체가 선언조차 되지 않은 상태
var a;
a; // undefined
b; // ReferenceError , undeclared
선언되지 않은 변수
예를들어, 프로그램의 디버그 모드를 DEBUG 라는 전역 변수로 조정한다면, 콘솔 창에 메시지 로깅 등 디버깅 작업을 수행하기 전, 이 변수의 선언 여부를 체크해야 한다.
debug.js 파일에만 선언하고, 개발/테스트 단계에서 이 파일을 브라우저가 로딩하기만 하면 될 것이다. 그러나 나머지 애플리케이션 코드에서 ReferenceError가 나지 않게 하려면 조심해서 DEBUG 전역 변수를 체크해야 한다. 이때 typeof 안전 가드가 유용하게 쓰인다.
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 "./1.3.utility";
console.log(product(1, 2)); //2
console.log(sum(1, 2)); //3
/**
* DEBUG 임의로 정한 변수
*/
// 에러 발생
if (DEBUG) {
console.log("디버깅을 시작합니다.");
}
// 존재 여부 체크 가능
if (typeof DEBUG !== "undefined") {
console.log("디버깅을 시작합니다.");
}
DEBUG와 같이 임의로 정의한 변수를 쓰지 않더라도 이런 식으로 체크하는 것이 편리하며, 내장 API 기능을 체크할 때에도 에러가 나지 않게 도와준다.
if (typeof atob === "undefined") {
atob = function () {
/* ... */
};
}
존재하지 않는 기능을 추가하기 위해 Polyfill(폴리필: 브라우저가 지원하지 않는 자바스크립트 코드를 지원 가능하도록 변환한 코드) 을 정의하려면 atob 선언문에서 var키워드를 빼는 것이 좋다. var atob 로 선언하면 선언 자체가 최상위 스코프로 호이스팅 된다. (아래 코드 참고)
var atob; // 선언문 호이스팅
if (typeof atob === "undefined") {
atob = function () {
/* ... */
};
}
window 객체를 통한 전역 변수 참조는 가급적 삼가는 것이 좋다. 전역 변수를 꼭 window 객체로만 호출하지 않는 다중 자바스크립트 환경이라면 더욱 그렇다.