자바스크립트 데이터 타입
자바스크립트의 값은 크게 기본 타입과 참조 타입으로 나뉜다. 기본 타입에는 number, string, boolean, undefined, null 이 있고, 참조 타입은 객체 타입이 있다. 즉, 기본 타입을 제외하면 전부 객체 타입이라고 할 수 있는데, 배열, 함수, 정규표현식 모두 자바스크립트 객체이다.
기본 타입은 하나의 실제 값을 가진다. 예를 들어 number 타입은 1.5 , string 타입은 “javascript” 라는 실제 값을 가진다. 하지만 참조 타입은 실제 값이 아닌 참조값을 갖는다. 즉, 참조 타입은 객체를 참조하는 값을 저장할 뿐 실제 객체를 나타내지는 않는다.


자바스크립트 객체
자바스크립트에서 객체는 단순히 이름(key):값(value) 형태의 프로퍼티를 저장하는 컨테이너다. 참조 타입인 객체는 여러개의 프로퍼티들을 포함할 수 있으며, 객체의 프로퍼티는 기본 타입이나 다른 객체를 포함할 수 있다.
객체와 객체 프로퍼티 생성 방법
// 객체 리터럴 방식
const yuri = {
name: 'yuri',
age: 27,
gender: 'female'
}
// Object()를 이용하여 빈 객체 생성
const yuri = new Object();
// yuri 객체에 프로퍼티 생성
yuri.name = 'yuri';
yuri.age = 27;
yuri.gender = 'female';
객체 접근 방법
console.log(yuri.name);
console.log(yuri['name']);
// 접근하려는 프로퍼티의 이름이 표현식이거나 예약어일 경우 대괄호 연산자만 이용한다
console.log(yuri.full-name); (X)
console.log(yuri['full-name']); (O)
// 없는 프로퍼티는 undefined
console.log(yuri.nickname); // undefined
객체 프로퍼티 삭제
delete yuri.gender;
console.log(yuri.gender); // female
delete yuri (x) // delete는 프로퍼티만 삭제하지 객체를 삭제할 순 없다
객체 프로퍼티 출력
for (var prop in yuri) {
console.log(prop, yuri[prop]);
}
객체 비교
객체는 참조값을 갖고 있기 때문에 동등 연산자(==)를 사용하여 두 객체를 비교하면, 객체의 프로퍼티 값이 아니라 참조값을 비교한다.
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(objB == objC); // true
참조에 의한 호출방식
기본 타입과 참조 타입은 함수 호출 방식도 다르다. 기본 타입은 값에 의한 호출(call by value)방식으로, 참조 타입은 참조에 의한 호출(call by reference)방식으로 동작한다.
먼저 call by value 방식은 함수를 호출할 때 인자로 기본 타입의 값을 넘길 경우, 호출된 함수의 매개변수에는 복사된 값이 전달된다. 그래서 함수 내부에서 매개변수의 값을 변경해도, 실제로 호출된 변수의 값은 아무 영향이 없다. 그러나 call by reference 방식은 함수를 호출할 때 인자로 참조 타입을 넘길 경우, 매개변수에는 프로퍼티가 복사된 객체가 전달되는 것이 아니라 원본 객체의 참조값이 그대로 전달된다. 그래서 함수 내부에서 실제 객체의 값을 변경하는 것이 가능해진다.
var a = 100;
var objA = { value: 100 };
function changeArg(num, obj) {
num = 200;
obj.value = 200;
console.log(num);
console.log(obj);
}
changeArg(a, objA);
console.log("--------------");
console.log(a);
console.log(objA);
// 출력 결과
200
{ value: 200 }
--------------
100
{ value: 200 }
자바스크립트 배열
배열은 자바스크립트 객체의 특별한 형태다. C나 JAVA의 배열과 기능은 같지만 다른 점이 많다. 자바스크립트의 배열은 굳이 크기를 정하지 않아도 되고, 어떤 위치에 어떤 타입의 데이터를 저장해도 에러가 발생하지 않는다. 심지어 일반 객체처럼 프로퍼티를 넣는 것도 가능하다.
배열과 배열의 요소 생성 및 접근
배열 리터럴은 자바스크립트에서 새로운 배열을 만드는 데 사용하는 표기법이다. 객체 리터럴이 중괄호 {} 를 이용한 표기법이었다면, 배열 리터럴은 대괄호 [] 를 사용한다. 그리고 Object() 를 사용해서 객체를 생성했던 것 처럼 Array() 생성자로 배열을 생성할 수도 있다. 생성자를 사용할 때는 new 연산자를 같이 써줘야 한다.
// 배열 리터럴을 통한 배열 생성
var colorArr = ['orange', 'yellow', 'blue', 'green', 'red'];
// 빈 배열 생성
var emptyArr = [];
emptyArr[0] = 100;
emptyArr[3] = 'three';
emptyArr[7] = true;
console.log(emptyArr.length); // 8
console.log(emptyArr);
// [100, undefined × 2, 'three', undefined × 3, true]
console.log(emptyArr[0]); // 100
console.log(emptyArr[1]); // undefined
console.log(emptyArr[9]); // undefined
배열의 length 프로퍼티
자바스크립트의 모든 배열은 length 프로퍼티가 있다. length 프로퍼티는 배열의 원소 개수를 나타내지만, 실제로 배열에 존재하는 원소 개수와 일치하는 것은 아니다. emptyArr 에는 실제로 3개의 요소가 있지만 emptyArr.length 는 8인 것처럼 말이다. 즉, length 프로퍼티는 배열 내 가장 큰 인덱스에 1을 더한 값이다. 그래서 실제 메모리가 length 크기만큼 할당된다는 보장은 없다.
가장 큰 인덱스 값이 변하면 length 값 또한 자동으로 거기에 맞춰 변경된다. 하지만 코드를 통해 length 프로퍼티 값을 명시적으로 변경할 수도 있다.
var arr = [0, 1, 2]; // arr.length = 3
arr.length = 5; // arr.length = 5
console.log(arr); // [0, 1, 2, undefined x 2]
arr.length = 2; // arr.length = 2
console.log(arr); // [0, 1]
만약 마지막 경우처럼 기존 length 보다 작은 크기로 변경된다면 length 프로퍼티를 벗어나는 인덱스 값들이 실제로 삭제된다. 즉, console.log(arr[2]) 를 하면 undefined 가 출력된다.
배열 표준 메서드와 length 프로퍼티
자바스크립트는 배열에서 사용 가능한 다양한 표준 메서드를 제공하며, 배열 메서드는 length 프로퍼티를 기반으로 동작한다. 예를 들어 push() 메서드는 인수로 받은 항목을 배열의 끝에 추가하는 함수인데, 해당 함수는 현재 length 값의 위치에 새로운 원소값을 추가한다. 만약 length 프로퍼티를 임의로 변경하면, 변경된 length 값의 위치에 추가된다. 즉, length 프로퍼티를 기반으로 움직인다는 것을 알 수 있다.
배열 vs 객체
배열도 객체이다. 그래서 typeof 연산자를 사용해보면 배열과 객체를 모두 object 라는 문자열을 반환하며, 배열도 객체의 특성을 갖고 있다. 하지만 둘 사이의 차이점은 존재한다. 배열에는 length 프로퍼티가 있지만 배열을 제외한 객체에는 length 프로퍼티가 없다. 그리고 배열의 표준 메서드, 예를 들어 push() 와 같은 함수는 배열만 호출 할 수 있다.

이는 배열과 객체의 프로토타입(부모)이 다르기 때문이다. 객체의 __proto__ 는 Object.prototype 이며, 배열의 __proto__ 는 Array.prototype 이다. 하지만 Array.prototype 의 __proto__ 는 다시 Object.prototype 을 가르키고 있다. 그래서 배열이 객체 특성과 배열만의 특성을 함께 가질 수 있는 것이다. 참고로 length와 push() 는 Array.prototype 에만 정의되어 있다.
배열의 프로퍼티 동적 생성
배열도 자바스크립트 객체이므로, 인덱스가 숫자인 배열 원소 이외에도 객체처럼 프로퍼티를 추가할 수 있다. 하지만 배열에 동적 프로퍼티가 추가될 경우 length는 변화가 없다. length는 배열 원소의 가장 큰 인덱스가 변했을 때만 변경된다.
var arr = [0, 1, 2]; // length = 3
arr.color = 'blue'; // length = 3
arr[3] = 3; // length = 4
console.log(arr);

배열 프로퍼티의 열거
for (var prop in arr) {
console.log(prop, arr[prop]);
}
for (var i = 0; i < arr.length; i++) {
console.log(i, arr[i]);
}
// 1번 출력 결과
0 0
1 1
2 2
3 3
color blue
// 2번 출력 결과
0 0
1 1
2 2
3 3
배열의 삭제
console.log(arr); // [0, 1, 2, 3]
delete arr[3];
console.log(arr); // [0, 1, 2, undefined]
console.log(arr.length) // 4
delete로 요소를 삭제하면 delete 연산자는 해당요소의 값을 undefined 로 변경할 뿐 원소 자체를 삭제하지 않는다. 만약 원소를 완전히 삭제하고 싶다면 splice() 배열 메서드를 사용한다.
splice(start, deleteCount, item…)
- start : 배열에서 시작 위치
- deleteCount : start 에서 지정한 시작 위치부터 삭제할 요소의 수
- item : 삭제할 위치에 추가할 요소
var arr = [0, 1, 2, 3];
arr.splice(2, 1); // 2번째 요소를 시작점으로 1개의 원소를 삭제한다
console.log(arr); // [0, 1, 3]
console.log(arr.length); // 3
유사 배열 객체
배열의 length 프로퍼티는 배열의 동작에 있어서 중요한 프로퍼티다. 그렇다면 만약 일반 객체에 length라는 프로퍼티가 있다면 어떻게 될까? 자바스크립트에서는 length 프로퍼티를 가진 객체를 유사 배열 객체 라고 한다. 유사 배열 객체의 가장 큰 특징 중 하나는 객체임에도 불구하고, 자바스크립트의 표준 배열 메서드를 제한적으로 사용할 수 있다. 바로 apply() 메서드를 사용하는 것이다.
var arr = ['hi'];
var obj = {
name: 'jwoo',
length: 2
};
arr.push('hello');
console.log(arr); // ['hi', 'hello']
Array.prototype.push.apply(obj, ['jiwon']);
console.log(obj); // { 2: 'jiwon', name: 'jwoo', length: 3 };
'자바스크립트' 카테고리의 다른 글
| this (0) | 2023.03.17 |
|---|---|
| callback, promise, async/await (0) | 2023.03.14 |
| 이벤트 위임 (0) | 2023.03.11 |
| Hoisting과 Temporal Dead Zone (0) | 2023.03.06 |
| 스코프 (0) | 2023.03.03 |