-
[Javascript] 데이터 타입과 변수javascript 2022. 10. 24. 17:58
poiemaweb에서 javascript 기본 문법에 대해 복습하던 중 헷갈리거나 제대로 알지 못했던 부분들이 있어 기록으로 남기고자 한다.
웹 프로그래밍 튜토리얼 | PoiemaWeb
Front-end Development Tutorial
poiemaweb.com
javascript 는 동적 타입(Dynamic/Weak Type) 언어이다.
변수의 타입 지정(Type annotation)없이 값이 할당되는 과정에서 자동으로 변수의 타입이 결정(타입 추론, Type Inference)된다.
즉, 변수는 고정된 타입이 없다. 따라서 같은 변수에 여러 타입의 값을 자유롭게 할당할 수 있다.
1. 데이터 타입
데이터 타입(Data Type)은 프로그래밍 언어에서 사용할 수 있는 데이터(숫자, 문자열, 불리언 등)의 종류를 말한다.
javascript의 모든 값은 데이터 타입을 갖는다.
ECMAScript 표준(ECMAScript 2015 (6th Edition), 이하 ES6)은 7개의 데이터 타입을 제공한다
원시 타입 (primitive data type)
- boolean
- null
- undefined
- number
- string
- symbol (ES6에서 추가)
객체 타입 (object/reference type)
- object(1) 원시 타입 (Primitive Data Type)
원시 타입의 값은 변경 불가능한 값(immutable value)이며 pass-by-value(값에 의한 전달)이다.
(1-1) number
ECMAScript 표준에 따르면 모든 수를 실수로 처리하며 정수만을 표현하기 위한 특별한 데이터 타입(integer type)은 없다.
(1-2) string
문자열은 배열처럼 인덱스를 통해 접근할 수 있다. 이와 같은 특성을 갖는 데이터를 유사 배열이라 한다.
한번 생성된 문자열은 read only로서 변경할 수 없다. 이것을 변경 불가능(immutable)이라 한다.
그러나 새로운 문자열을 재할당하는 것은 물론 가능하다. 이는 기존 문자열을 변경하는 것이 아니라 새로운 문자열을 새롭게 할당하는 것이기 때문이다.
var str = 'string'; console.log(str); // string str = 'String'; console.log(str); // String str += ' test'; console.log(str); // String test
(1-3) boolean
불리언(boolean) 타입의 값은 논리적 참, 거짓을 나타내는 true와 false 뿐이다.
비어있는 문자열과 null, undefined, 숫자 0은 false로 간주된다.
(1-4) undefined
undefined 타입의 값은 undefined가 유일하다. 선언 이후 값을 할당하지 않은 변수는 undefined 값을 가진다.
(1-5) null
null 타입의 값은 null이 유일하다. javascript는 대소문자를 구별(case-sensitive)하므로 null은 Null, NULL등과 다르다.
프로그래밍 언어에서 null은 의도적으로 변수에 값이 없다는 것을 명시할 때 사용한다.
typeof 연산자로 null 값을 연산해 보면 null이 아닌 object가 나온다. 이는 자바스크립트의 설계상의 오류이다.
따라서 null 타입을 확인할 때 typeof 연산자를 사용하면 안되고 일치 연산자(===)를 사용하여야 한다.
(1-6) symbol
심볼(symbol)은 ES6에서 새롭게 추가된 7번째 타입으로 변경 불가능한 원시 타입의 값이다.
심볼은 주로 이름의 충돌 위험이 없는 유일한 객체의 프로퍼티 키(property key)를 만들기 위해 사용한다.
심볼은 Symbol 함수를 호출해 생성한다. 이때 생성된 심볼 값은 다른 심볼 값들과 다른 유일한 심볼 값이다.
// 심볼 key는 이름의 충돌 위험이 없는 유일한 객체의 프로퍼티 키 var key = Symbol('key'); console.log(typeof key); // symbol var obj = {}; obj[key] = 'value'; console.log(obj[key]); // value
(2) 객체 타입 (Object type, Reference type)
객체는 데이터와 그 데이터에 관련한 동작(절차, 방법, 기능)을 모두 포함할 수 있는 개념적 존재이다.
달리 말해, 이름과 값을 가지는 데이터를 의미하는 프로퍼티(property)와 동작을 의미하는 메소드(method)를 포함할 수 있는 독립적 주체이다.
javascript는 객체(object) 기반의 스크립트 언어로서 javascript를 이루고 있는 거의 모든 것이 객체이다.
원시 타입(Primitives)을 제외한 나머지 값들(배열, 함수, 정규표현식 등)은 모두 객체이다.
또한 객체는 pass-by-reference(참조에 의한 전달) 방식으로 전달된다.
2. 변수
변수(Variable)는 프로그램에서 사용되는 데이터를 일정 기간 동안 기억하여 필요한 때에 다시 사용하기 위해 데이터에 고유의 이름인 식별자(identifier)를 명시한 것이다.
변수에 명시한 고유한 식별자를 변수명이라 하고 변수로 참조할 수 있는 데이터를 변수값이라 한다.
변수는 var, let, const 키워드를 사용하여 선언하고 할당 연산자를 사용해 값을 할당한다. 그리고 식별자인 변수명을 사용해 변수에 저장된 값을 참조한다.
(1) 변수 호이스팅(Variable Hoisting)
console.log(foo); // ① undefined var foo = 123; console.log(foo); // ② 123 { var foo = 456; } console.log(foo); // ③ 456
①에서 변수 foo는 아직 선언되지 않았으므로 ReferenceError: foo is not defined가 발생할 것을 기대했겠지만 콘솔에는 undefined가 출력된다.
왜냐하면 다른 C-family 언어와는 차별되는 javascript의 특징으로 모든 선언문은 호이스팅(Hoisting)되기 때문이다.
호이스팅이란 var 선언문이나 function 선언문 등 모든 선언문이 해당 Scope의 선두로 옮겨진 것처럼 동작하는 특성을 말한다.
즉, javascript는 모든 선언문(var, let, const, function, function*, class)이 선언되기 이전에 참조 가능하다.
[여기서 function*이란?]
function* 선언은 generator function을 정의하는데, 이 함수는 Generator 객체를 반환한다.
generator는 이터레이터를 만드는 함수로서 이터레이터의 next()를 활용하여 값을 지연 평가(로직에서 뒤늦게 값이 필요할 때 만들어내는 방식)할 수 있게 된다.변수가 어떻게 생성되며 호이스팅은 어떻게 이루어지는지 아래를 통해 좀 더 자세히 살펴보자.
변수는 3단계에 걸쳐 생성된다.
- 선언 단계(Declaration phase)
변수 객체(Variable Object)에 변수를 등록한다. 이 변수 객체는 스코프가 참조하는 대상이 된다.
- 초기화 단계(Initialization phase)
변수 객체(Variable Object)에 등록된 변수를 메모리에 할당한다. 이 단계에서 변수는 undefined로 초기화된다.
- 할당 단계(Assignment phase)
undefined로 초기화된 변수에 실제값을 할당한다.var 키워드로 선언된 변수는 선언 단계와 초기화 단계가 한번에 이루어진다.
즉, 스코프에 변수가 등록되고 변수는 메모리에 공간을 확보한 후 undefined로 초기화된다.
그러므로 변수 선언문 이전에 변수에 접근하여도 Variable Object에 변수가 존재하기 때문에 에러가 발생하지 않는다. 다만 undefined를 반환한다. 이러한 현상을 변수 호이스팅(Variable Hoisting)이라한다.
이후 변수 할당문에 도달하면 비로소 값의 할당이 이루어진다.
javascript의 변수는 다른 C-family와는 달리 블록 레벨 스코프(block-level scope)를 가지지 않고 함수 레벨 스코프(function-level scope)를 갖는다.
단, ECMAScript 6에서 도입된 let, const 키워드를 사용하면 블록 레벨 스코프를 사용할 수 있다.
- 함수 레벨 스코프(Function-level scope)
함수 내에서 선언된 변수는 함수 내에서만 유효하며 함수 외부에서는 참조할 수 없다.
즉, 함수 내부에서 선언한 변수는 지역 변수이며 함수 외부에서 선언한 변수는 모두 전역 변수이다.
- 블록 레벨 스코프(Block-level scope)
코드 블록 내에서 선언된 변수는 코드 블록 내에서만 유효하며 코드 블록 외부에서는 참조할 수 없다.(2) var 키워드로 선언된 변수의 문제점
ES5에서 변수를 선언할 수 있는 유일한 방법은 var 키워드를 사용하는 것이다.
var 키워드로 선언된 변수는 아래와 같은 특징을 갖는다. 이는 다른 C-family 언어와는 차별되는 특징(설계상 오류)으로 주의를 기울이지 않으면 심각한 문제를 발생시킨다.
1. 함수 레벨 스코프(Function-level scope)
- 전역 변수의 남발
- for loop 초기화식에서 사용한 변수를 for loop 외부 또는 전역에서 참조할 수 있다.
2. var 키워드 생략 허용
의도하지 않은 변수의 전역화
3. 중복 선언 허용
의도하지 않은 변수값 변경
4. 변수 호이스팅
변수를 선언하기 전에 참조가 가능하다.ES6는 이러한 var의 단점을 보완하기 위해 let과 const 키워드를 도입하였다.
'javascript' 카테고리의 다른 글
[Javascript] insertAdjacentHTML (0) 2023.01.30 [Javascript] JSDoc (0) 2022.10.26 [Javascript] 객체와 불변성(Immutability) (0) 2022.10.26 [Javascript] 객체 (0) 2022.10.25 [Javascript] 단축평가 (0) 2022.10.25