자바스크립트의 타입

  • 기본 타입
    • number, string, boolean, null, undefined
  • 참조 타입
    • Object, Array

기본 타입

숫자, 문자열, 불린, null, undefined가 있다. 기본 타입의 특징은 그 자체가 하나의 값을 나타낸다.

숫자

C언어는 int, long, float, double 같은 여러 숫자 타입이 존재하지만, 자바스크립트는 number라는 하나의 숫자형만 존재한다. 자바스크립트에서는 모든 숫자를 64비트 부동 소수점 형태로 저장하기 때문이다. C언어의 double과 유사하다.

특징

  • 정수형이 따로 없다
  • 모든 숫자를 64비트 부동 소수점 형태
  • 모든 숫자를 실수로 처리하므로 나눗셈 연산에 주의해야 한다.

문자열

문자열은 작은 따옴표(‘)나 큰 따옴표(“)로 생성할 수 있다.

특징

  • C언어에서의 char 타입처럼 문자 하나만을 별도로 나타내는 데이터 타입은 없다.
  • 한 번 정의된 문자열은 변하지 않는다.
1
2
3
4
5
6
7
var str = 'test';
console.log(str[0], str[1], str[2], str[3]);
// (출력값) test

str[0] = 'T';
console.log(str);
// (출력값) test

불린값(boolean)

자바스크립트에는 true와 false를 나타내는 boolean 타입이 있다.

null과 undefined

null과 undefined는 ‘값이 비어있음’을 나타낸다. 자바스크립트 환경 내에서 기본적으로 할당되지 않는 변수는 undefined 타입이고 값도 undefined이다. 즉 undefined는 타입이자, 값을 나타낸다.

undefined가 아직 값을 할당하지 않아서 비어있는 값이라면, null은 개발자가 명시적으로 값이 없다는 것을 나타낼 때 사용한다. 그래서 undefined는 타입도 undefined지만 null 값을 넣은 변수의 타입은 object이다.

1
2
3
4
var nullVar = null;

console.log(typeof nullVar === null); // (출력값) false
console.log(nullVar === null); // (출력값) true

특징

  • undefined, null는 값이 비어있다는 의미
  • undefined는 아직 값을 할당하지 않은 것, null은 일부러 값이 비어있음을 명시할 때
  • undefined는 타입이자 값
  • null의 타입은 object

참조 타입 (객체)

자바스크립트에서 기본 타입을 제외한 모든 값은 객체이다. 배열, 함수, 정규표현식 등도 모두 객체다. 즉 참조 타입은 객체 타입이다.

자바스크립트 객체는 이름(key): 값(value) 형태의 프로퍼티들을 저장하는 컨테이너이다. 이것은 컴퓨터 과학 분야에서 해시(Hash)라는 자료구조와 유사하다.

객체 생성

객체를 생성하는 방법은 3가지가 있다.

  • Object() 생성자 함수
1
2
3
4
5
6
7
8
var foo = new Object();

foo.name = 'foo';
foo.age = 30;
foo.gender = 'male';

console.log(typeof foo); // (출력값) object
console.log(foo); // (출력값) { name: 'foo', age: 30, gender: 'male' }
  • 객체 리터럴 방식 이용
1
2
3
4
5
6
7
8
var foo = {
name: 'foo',
age: 30,
gender : 'male'
};

console.log(typeof foo);
console.log(foo);
  • 생성자 함수
1
2
3
4
5
6
7
8
var Foo = function(name, age, gender) {
this.name = name;
this.age = age;
this.gender = gender;
};

var f = new Foo('foo', 30, 'male');
console.log(f.name); // (출력값) foo

객체 프로퍼티 읽기/쓰기/갱신

객체의 프로퍼티 접근법은 2가지가 있다.

  • 대괄호([]) 표기법
  • 마침표(.) 표기법

프로퍼티 읽기

1
2
3
4
5
6
7
var foo = {
name : 'foo',
major : 'compute science'
};

console.log(foo.name); // (출력값) foo
console.log(foo['name']); // (출력값) foo

프로퍼티 갱신

1
2
3
4
5
6
7
var foo = {
name : 'foo',
major : 'compute science'
};

foo.major = 'electronics engineering';
console.log(foo['major']); // (출력값) electronics engineering

프로퍼티 동적 생성

객체 생성 후에도 동적으로 프로퍼티를 추가할 수 있다.

1
2
3
4
5
6
7
var foo = {
name : 'foo',
major : 'compute science'
};

foo.age = 30;
console.log(foo.age); // (출력값) 30

접근하는 값이 있으면 갱신되고 없으면 동적으로 생성해 추가된다.

대괄호 표기법만 사용해야 하는 경우

접근하려는 프로퍼티가 표현식이거나 예약어일 경우 대괄호 표기법만 사용한다.

1
2
3
4
5
6
7
8
var foo = {
name : 'foo',
major : 'compute science',
};

foo['full-name'] = 'foo bar';
console.log(foo.full-name); // (출력값) NaN
console.log(foo.['full-name']); // (출력값) foo bar

이 예제에서 프로퍼티 이름에 -연산자가 포함되어 있어 마침표 표기법으로 접근할 수 없다.

NaN (Not a Number)

자바스크립트에서 수치 연산을 해서 정상적인 값을 얻지 못할 때 출력되는 값이다.

객체 참조값

객체를 왜 참조 타입이라고 부를까?

객체의 모든 연산이 실제 값이 아닌 참조값으로 처리되기 때문이다.

1
2
3
4
5
6
7
8
9
10
11
var objA = {
val : 40
};
var objB = objA;

console.log(objA.val); // (출력값) 40
console.log(objB.val); // (출력값) 40

objB.val = 50;
console.log(objA.val); // (출력값) 50
console.log(objB.val); // (출력값) 50

변수 objB에 objA를 할당하면 값을 할당하는 것이 아닌 참조값이 저장되기 때문에 값을 바꾸면 참조하고 있는 모든 객체의 값이 바뀐다.

객체 비교

동등 연산자(==)를 사용하여 객체를 비교할 때도 프로퍼티 값이 아닌 참조값을 비교한다.

1
2
3
4
5
6
7
8
9
10
var a = 100;
var b = 100;

var objA = { value: 100 };
var objB = { value: 100 };
var objC = objB;

console.log(a == b); // (출력값) true
console.log(objA == objB); // (출력값) false
console.log(objA == objC); // (출력값) true

호출 방식의 차이

기본 타입은 값에 의한 호출 방식이나, 참조 타입은 참조에 의한 호출 방식이다.

함수를 호출할 때 인자로 기본 타입의 값을 넘길 경우, 호출된 함수의 매개변수로 복사된 값이 전달된다. 그래서 함수 내부에서 매개변수의 값을 변경해도 호출된 변수의 값이 변경되지는 않는다.

이에 반해 함수를 호출할 때 인자로 참조 타입인 객체를 넘길 경우, 그 객체 참조값이 넘어가게 되어 함수 내부에서 매개변수의 값을 변경할 수 있게된다.

프로토타입

자바스크립트의 모든 객체는 자신의 부모 역할을 하는 객체와 연결되어 있다. 이러한 부모 객체를 프로토타입 객체라고 부른다.

ECMAScript 명세서에는 자바스크립트의 모든 객체는 자신의 프로토타입을 가리키는 [[Prototype]]이라는 숨겨진 프로퍼티를 가지고 있다고 한다.

객체 리터럴 방식으로 생성된 객체의 경우 Objsect.prototype 객체가 프로토타입 객체가 된다.

배열

다른 언어들과 다르게 자바스크립트 배열은 크기를 지정하지 않아도 되며, 어떤 위치에 어느 타입의 데이터를 저장해도 된다.

배열 리터럴

배열을 생성하는데 사용하는 표기법이다.

1
var colorArr = ['orange', 'yellow', 'blue'];

배열 요소 생성

아무 인덱스 위치에 값을 동적으로 넣을 수 있다. 대신 앞의 인덱스가 정의되지 않았다면 undefined가 기본값으로 들어가며 생긴다. 하지만 그렇다고 실제 메모리도 생긴 배열처럼 할당되진 않는다.

1
2
3
4
5
6
var emptyArr = [];

emptyArr[0] = 100;
emptyArr[3] = 'eight';
console.log(emptyArr);
// (출력값) [100, undefined, undefined, "eight"]

배열의 length 프로퍼티

배열은 모두 length 프로퍼티가 있다. length 프로퍼티는 배열 내에 가장 큰 인덱스에 1을 더한 값이다.

length 프로퍼티는 명시적으로 값을 변경할 수도 있다.

1
2
3
4
5
6
7
8
9
var arr = [0, 1, 2];
console.log(arr.length); // (출력값) 3

arr.length = 5;
console.log(arr); // (출력값) [0, 1, 2, undefined, undefined]

arr.length = 2;
console.log(arr); // (출력값) [0, 1]
console.log(arr[2]); // (출력값) undefined

이렇게 length를 수정하면 length가 가리키는 위치가 변경된다.

length를 할당한 원소보다 안으로 설정하면 length를 벗어나는 값은 삭제되기 때문에 접근하면 undefined가 나온다.

배열의 프로토타입

객체와 배열의 큰 차이점은 배열만의 표준 메소드 존재 여부이다. push(), pop() 같은 메소드는 객체에서는 사용할 수 없다. 하지만 나머지는 Array.prototype도 결국 Object.prototype이 부모이기 때문에 큰 차이가 없다.

배열 요소 삭제

배열도 객체이므로 delete연산자로 삭제할 수 있다.

1
2
3
4
var arr = ['zero', 'one', 'two', 'three'];
delete arr[2];
console.log(arr); // (출력값) ['zero', 'one', undefined, 'three']
console.log(arr.length); // (출력값) 4

delete는 해당 요소의 값을 undefined로 설정할 뿐 원소 자체를 삭제하지는 않는다.

Array() 생성자 함수

Array() 생성자 함수는 인자 개수에 따라 동작이 다르다.

  • 인자가 1개이고 숫자일 때 : 호출된 인자를 length로 갖는 빈 배열 생성
  • 그외의 경우 : 호출된 인자를 요소로 갖는 배열 생성
1
2
var foo = new Array(3);       // [undefined, undefined, undefined]
var bar = new Array(1, 2, 3); // [1, 2, 3]

기본 타입의 표준 메소드

자바스크립트는 숫자, 문자열, 불린값에 대해 각 타입별로 호출 가능한 표준 메소드를 정의하고 있다.

기본 타입의 경우 객체가 아닌데 어떻게 메소드를 호출할 수 있을까?

기본 타입의 값들이 메소드를 호출한 경우, 이들 기본값은 메소드 처리 순간에 객체로 변환된 다음 각 타입별 표준 메소드(charAt())를 호출한다. 그 메소드가 끝나면 다시 기본값으로 복귀하게 된다.

1
console.log("test".charAt(2)); // (출력값) 's'