데이터 타입과 변수

테루·2021년 4월 6일
0

변수

변수는 값의 위치를 기억하는 저장소이다. 값의 위치란 값이 위치하고 있는 메모리 상의 주소를 의미한다.

즉 변수란 값이 위치하고 있는 메모리 주소에 접근하기 위해 사람이 이해할 수 있는 언어로 명명한 식별자이다.

메모리에 값 저장

메모리에 값을 저장하기 위해서는 먼저 메모리 공간을 확보해야 할 메모리의 크기(byte)를 알아야한다.
(데이터 타입에 따라 확보해야할 메모리의 크기가 다르다.)

자바스크립트에서의 변수

자바스크립트는 동적 타입 언어이다. C언어같은 경우 변수를 설정하기전에 변수의 type을 명명해야되는데 자바스크립트는 고정된 타입이 없기 때문에 type의 이름을 설정하지 않아도 된다.

다만 개발중 자신이 변수를 어떤 타입으로 정했는지 헷갈릴 우려가 있다.

데이터 타입

데이터 타입은 프로그래밍 언어에서 사용할 수있는 데이터의 종류를 말한다.

데이터 타입은 한정된 메모리 공간을 효율적으로 사용하기 위해서 그리고 2진수 데이터로 메모리에 저장된 데이터를 다양한 형태로 사용하기 위해 존재한다.

  • 원시 타입
  • boolean, null, undefined, number, string, symbol
  • 객체 타입
  • object

원시 타입

원시 타입의 값은 변경 불가능한 값이며 pass-by-value(값에 의한 전달)이다.

number

자바스크립트는 C나 java와는 다르게 하나의 숫자 타입만 가지고 있다.
다른 프로그래밍 언어들은 int, float, double, long등과 같은 다양한 숫자타입을 가지고 있다.

ECMAScript 표준에 따르면 숫자타입의 값은 배정밀도 64bit 부동소수점 형을 따른다고 한다.
즉 모든 수를 실수를 처리하며 정수만을 표현하기 위한 특별한 데이터 타입은 없다.

let integer = 10; //정수
let double = 10.12; //실수
let negative = -20; //음의 정수
let binary = 0b01000001; //2진수
let octal = 0o101; //8진수
let hex = 0x41; // 16진수

자바스크립트는 2진수, 8진수, 16진수 데이터 타입을 제공하지 않기 때문에 이들 값을 참조하면 모두 10진수로 해석된다.

자바스크립트의 숫자 타입은 정수만을 위한 타입이 없고 모든 수를 실수로 처리한다. 정수로 표시된다 해도 사실은 실수다. 따라서 정수로 표시되는 수끼리 나누더라도 실수가 나올수 있다.

string

string 타입은 텍스트 데이터를 나타내는데 사용된다. 문자열은 0개 이상의 16bit 유니코드 문자들의 집합으로 대부분으 ㅣ전세계의 문자를 표현할 수 있다. 문자열은 작은 따옴표 또는 큰 따옴표 안에 택스트를 넣어 생성한다.
가장 일반적인 표기법은 작은 따옴표를 사용하는 것이다.

let string = '문자열'; // 작은 따옴표
string = "문자열"; //큰 따옴표
string = `문자열` // 백틱

자바스크립트는 C와 같은 언어와는 다르게 문자열이 원시타입이므로 변경 불가능하다. 이것은 한번 생성하면 문자열을 변경 할 수 없다는 것을 의미한다.

let str = '문자열';
str = '다른 문자열';

첫번째 구문이 실행이 되면 메모리에 '문자열' 이 생성되고 식별자 str은 메모리에 생성된 문자열 '문자열'의 메모리 주소를 가리킨다. 그리고 두번째 구문이 실행이 되면 기존에 있던 '문자열'을 수정하는 것이 아니라 새로운 문자열인 '다른 문자열'을 메모리에 생성하고 식별자 str은 '다른 문자열'을 가리키게 된다.

문자열은 배열처럼 인덱스를 통해 접근할 수 있다. 이와 같은 특성을 갖는 데이터를 유사배열이라 한다.

let str = 'hello';

str[0] = 'S';

str[0] = "S"처럼 이미 생성된 문자열의 일부 문자를 변경해도 반영되지 않는다.
=> 변경 불가능 이기 때문이다.

하지만 아래와 같이 다른 값을 새로 할당하는 것은 가능하다.

let str = 'hello';
console.log(str); // hello

let str = 'String';
console.log(str); // String

let str += 'Jin';
console.log(str); // hello Jin

boolean

불리언은 참과 거짓을 나타내는 true와 false 값 만을 가진다.

true, false

undefined

undefined는 선언 후 값을 할당하지 않은 변수의 값을 말한다.
즉 선언은 되었지만 값을 할당하지 않은 변수에 접근하거나 존재하지 않는 객체 프로퍼티에 접근할 경우 undefined가 반환된다.

let a ;
console.log(a); // undefined

이는 처음 메모리 공간이 할당이 될때 빈 상태로 두는 것이 아니라 자바스크립트 엔진이 undefined로 초기화하기 때문에 undefined값이 나오는 것이다.

이것은 개발자가 의도적으로 할당한 값이 아니라는 것이다.

그렇다면 의도적으로 undefined를 할당해야될 때는 어떻게 해야하나?

그럴 때는 undefined를 사용하는 것이 아닌 null을 할당하는 것이 좋다.

null

null값도 undefined와 같이 null값 하나 만을 가지고 있다. 여기서 주의할 점은 자바스크립트는 대소문자를 구분하므로 Null, NULL, null은 모두 다른 값이라 할 수 있다.

null이란 의도적으로 변수에 값이 없다는 것을 명시할 때 사용된다. 이는 변수가 기억하는 메모리 어드레스의 참조 정보를 제거하는 것을 의미하며 자바스크립트 엔진은 누구도 참조하지 않는 메모리 영역에 대해서 가비지 컬렉션을 수행할 것이다.

let foo = 'Lee';
foo = null; //참조요소가 제거됨

또는 함수가 호출되었으나 유효한 값을 반환할 수 없는 경우, 명시적으로 null을 반환하기도 한다.

예를 들어 HTML요소를 검색해 반환하는 document.querySelector()는 조건에 부합하는 HTML 요소를 검색할 수 없는 경우 null을 반환한다.

null타입을 확인할 때
typeof 연산자로 null값을 연산해 보면 null값이 아니라 object로 나오는데 이것은 자바스크립트 설계상의 오류이다.

그래서 null 타입을 확인할 때 typeof 연산자 대신 ===를 사용해야 한다.

let foo = null;
console.log(foo === null); //true

symbol

심볼은 ES6에서 새롭게 추가된 7번째 타입으로 변경불가능한 원시 타입의 값이다.
심볼은 주로 이름의 충돌 위험이 없는 유일한 객체의 프로퍼티 키를 만들기 위해서 사용된다.


var key = Symbol('key');
console.log(typeof key); // symbol

var obj = {};
obj[key] = 'value';
console.log(obj[key]); // value

객체 타입

객체는 데이터와 그 데이터에 관련한 동작(절차, 방법, 기능)을 모두 포함할 수 있는 개념적 존재이다. 달리 말해, 이름과 값을 가지는 데이터를 의미하는 프로퍼티(property)와 동작을 의미하는 메소드(method)를 포함할 수 있는 독립적 주체이다.

자바스크립트는 객체(object) 기반의 스크립트 언어로서 자바스크립트를 이루고 있는 거의 “모든 것”이 객체이다. 원시 타입(Primitives)을 제외한 나머지 값들(배열, 함수, 정규표현식 등)은 모두 객체이다. 또한 객체는 pass-by-reference(참조에 의한 전달) 방식으로 전달된다.

변수의 선언

변수는 var, let, const 키워드를 사용해서 선언하고 할당 연산자를 사용해 값을 할당한다. 그리고 식별자인 변수명을 사용해 변수에 저장된 값을 참조한다.

변수명의 명명 규칙

  • 반드시 영문자, underscore(_), 또는 달러기호($)로 시작하여야된다. 그리고 이어지는 문자에는 숫자도 사용할 수 있다.
  • 자바스크립트에서는 대/소문자를 구별하므로 사용할 수 있는 문자는 "A"~"Z"와 "a"~"z"이다.
> 선언만 되어있는 변수는 undefined로 초기값을 갖는다. 선언하지 않는 변수에 접근하면 ReferenceError가 발생한다.

변수의 중복

let, var를 키워드로 사용한 변수는 중복 선언이 가능하다.
같은 변수명을 사용 했을때 나중에 선언한 변수명의 값으로 덮어쓰여진다.

var x = 1;
console.log(x); // 1

// 변수의 중복 선언
var x = 100;
console.log(x); // 100

왠만하면 사용하지 않는게 심신에 좋다....

동적 타이핑

자바스크립트는 동적 타입언어이다.

자료형의 명시없이 변수명만 가지고 선언 및 값을 전달하는 것이 가능하다.
확실히 개발자 입장에서는 런타임 중에 타입에 대한 결정을 진행 하므로 편리하지만 나중에 예기치 못한 에러가 발생할 수도 있고 이를 발견하는데 큰 어려움을 겪을 수 있다.

변수 호이스팅

호이스팅이란

함수안에 있는 선언들을 모두 끌어올려서 해당 함수 유효범위의 최상단에 선언하는 것을 말한다.
즉 선언들을 맨 위로 올리는 것을 말함

호이스팅 전

console.log("hello");
  var myname = "HEEE"; // var 변수 
  let myname2 = "HEEE2"; // let 변수 

호이스팅 결과

  /** --- JS Parser 내부의 호이스팅(Hoisting)의 결과 - 위와 동일 --- */
  var myname; // [Hoisting] "선언"
  console.log("hello");
  myname = "HEEE"; // "할당"
  let myname2 = "HEEE2"; // [Hoisting] 발생 X

호이스팅의 대상

var 변수 선언함수 선언문 에서만 호이스팅이 일어난다.

let과 const 변수 선언과 함수 표현식에서는 호이스팅이 발생하지 않는다는 말도 있지만
이것은 정확하지 않다.

var는 선언과 동시에 초기화가 진행된다. 즉 선언과 동시에 undefined가 할당이 된다는 것이다.

하지만 let 과 const는 다르다. 선언은 되지만 초기화가 이루어지지 않는다.
선언이 된후 TDZ(Temporary Dead Zone)에 들어가게 된다.

즉 선언은 되어있지만, 초기화가 되지 않아 이를 위한 자리가 메모리에 준비되어 있지 않은 상태라는 것이다.

결론

  • 호이스팅은 변수의 선언을 최상단에 끌어올린다는 뜻
  • var, let, const 모두 호이스팅 된다.
  • let은 선언과 동시에 TDZ에 들어가서 초기화가 필요한 별도의 상태로 관리된다.
  • const 는 선언과 동시에 초기화 할당까지 이루어진다.

var 키워드로 선언된 변수의 문제점

ES5에서 변수를 선언할 수 있는 유일한 방법은 var 키워드를 사용하는 것이다. var 키워드로 선언된 변수는 아래와 같은 특징을 갖는다. 이는 다른 C-family 언어와는 차별되는 특징(설계상 오류)으로 주의를 기울이지 않으면 심각한 문제를 발생시킨다.

  1. 함수 레벨 스코프(Function-level scope)
    • 전역 변수의 남발
    • for loop 초기화식에서 사용한 변수를 for loop 외부 또는 전역에서 참조할 수 있다.
  2. var 키워드 생략 허용
    • 의도하지 않은 변수의 전역화
  3. 중복 선언 허용
    • 의도하지 않은 변수값 변경
  4. 변수 호이스팅
    • 변수를 선언하기 전에 참조가 가능하다.
대부분의 문제는 전역 변수로 인해 발생한다. 전역 변수는 간단한 애플리케이션의 경우, 사용이 편리한 면이 있지만 불가피한 상황을 제외하고 사용을 억제해야 한다. 전역 변수는 유효 범위(scope)가 넓어서 어디에서 어떻게 사용될 지 파악하기 힘들다. 이는 의도치 않은 변수의 변경이 발생할 수 있는 가능성이 증가한다. 또한 여러 함수와 상호 의존하는 등 부수 효과(side effect)가 있을 수 있어서 복잡성이 증가한다.

변수의 유효 범위(scope)는 좁을수록 좋다.

ES6는 이러한 var의 단점을 보완하기 위해 let과 const 키워드를 도입하였다.

profile
아직은 달걀안의

0개의 댓글