본문 바로가기
IT

자바스크립트 참조 타입(객체 타입)

by csongin 2022. 7. 9.
728x90

자바스크립트 참조 타입(객체 타입)

자바스크립트에서 숫자, 문자열, 불린값, null, undefined 같은 기본 타입을 제외한 모든 값은 객체다.

따라서 배열, 함수, 정규표현식 등도 모두 결국 자바스크립트 객체로 표현된다.

 

자바스크립트에서 객체는 단순히 '이름(key):값(value)' 형태의 프로퍼티들을 저장하는 컨테이너로서,

컴퓨터 과학 분야에서 해시(Hash)라는 자료구조와 상당히 유사하다.

자바스크립트에서 기본 타입은 하나의 값만을 가지는 데 비해, 참조 타입인 객체는 여러 개의 프로퍼티들을 포함할 수 있으며,

이러한 객체의 프로퍼티는 기본 타입의 값을 포함하거나, 다른 객체를 가르킬 수도 있다.

이러한 프로퍼티의 성질에 따라 객체의 프로퍼티는 함수로 포함할 수 있으며, 자바스크립트에서는 이러한 프로퍼티를 메서드라고 부른다.

 

객체 생성

자바스크립트에서는 클래스라는 개념이 없고 객체 리터럴이나 생성자 함수 등 별도의 생성 방식이 존재한다.

자바스크립트에서 객체를 생성하는 방법은 크게 세 가지가 있다.

Object() 생성자 함수, 객체 리터럴, 생성자 함수

생성자 함수는 아직 안배워서 일단 패스!

Object() 생성자 함수

// Object()를 이용해서 foo 빈 객체 생성
var foo = new Object();

// foo 객체 프로퍼티 생성
foo.name = 'foo';
foo.age = 30;
foo.gender = 'male';

console.log(typeof foo); // object
console.log(foo); // { name: 'foo', age: 30, gender: 'male' }

객체 리터럴 방식

리터럴이란 용어의 의미는 표기법이다.

따라서 객체 리터럴이란 객체를 생성하는 표기법을 의미한다.

객체 리터럴은 중괄호 { }를 이용해서 객체를 생성한다. 중괄호 안에 아무것도 적지 않은 경우는 빈 객체가 생성되며,
중괄호 안에 "프로퍼티 이름":"프로퍼티값" 형태로 표기하면, 해당 프로퍼티가 추가된 객체를 생성할 수 있다.

프로퍼티 이름은 문자열이나 숫자가 올 수 있고, 프로퍼티 값으로는 자바스크립트의 값을 나타내는 어떤 표현식도 올 수 있으며,

이 값이 함수일 경우 메서드라고 부른다.

// 객체 리터럴 방식으로 foo 객체 생성
var foo = {
    name: 'foo',
    age: 30,
    gender: 'male'
};

console.log(typeof foo); // object
console.log(foo) // { name: 'foo', age: 30, gender: 'male' }

 

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

객체는 새로운 값을 가진 프로퍼티를 생성하고, 생성된 프로퍼티에 접근해서 해당 값을 읽거나 또는 원하는 값으로 프로퍼티의 값을 갱신할 수 있다.

객체의 프로퍼티에 접근하는 두 가지 방법

  • 대괄호 [ ] 표기법
  • 마침표 . 표기법
// 객체 리터럴 방식을 통한 foo 객체 생성
var foo = {
  name: 'foo',
  major: 'computer science'
};

// 객체 프로퍼티 읽기
console.log(foo.name); // foo
console.log(foo['name']); // foo
console.log(foo.nickname); // undefined

// 객체 프로퍼티 갱신
foo.major = 'electronics engineering';
console.log(foo.major); // electronics engineering
console.log(foo['major']); // electronics engineering

// 객체 프로퍼티 동적 생성
foo.age = 30;
console.log(foo.age); // 30

// 대괄호 표기법만을 사용해야 할 경우
foo['full-name'] = 'foo bar';
console.log(foo['full-name']); // foo bar
console.log(foo.full-name); // NaN
console.log(foo.full); // undefined
console.log(name); // undefined

프로퍼티 읽기

자바스크립트에서는 대괄호 표기법에서 접근하려는 프로퍼티 이름을 문자열 형태로 만들지 않으면 모든 자바스크립트 객체에서 호출 가능한 toString()이라는 메서드를 자동으로 호출해서 이를 문자열로 바꾸려는 시도를 한다.

만약 객체에 없는 프로퍼티에 접근하는 경우는 undefined 값이 출력된다.

 

프로퍼티 갱신

마침표 표기법을 이용한 방법 foo.major = 'electronics engineering';

대괄호 표기법을 이용한 방법 foo['major'] = 'electronics engineering';

 

프로퍼티 동적 생성

자바스크립트 객체의 프로퍼티에 값을 할당할 때, 프로퍼티가 이미 있을 경우는 해당 프로퍼티의 값이 갱신되지만, 

객체의 해당 프로퍼티가 없을 경우에는 새로운 프로퍼티가 동적으로 생성된 후 값이 할당된다.

 

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

접근하려는 프로퍼티가 표현식이거나 예약어일 경우다.

'full-name'의 경우 '-'연산자가 있는 표현식이다.

 

NaN (Not a Number) 값
자바스크립트에서 NaN(Not a Number)은 수치 연산을 해서 정상적인 값을 얻지 못할 때 출력되는 값이다.
가령, 1 - 'hello' 라는 연산의 결과는 NaN이다. 1이라는 숫자와 문자열 'hello'를 빼는 연산을 수행했기 때문이다.

for in 문과 객체 프로퍼티 출력

for in 문을 사용하면, 객체에 포함된 모든 프로퍼티에 대해 루프를 수행할 수 있다.

// 객체 리터럴을 통한 foo 객체 생성
var foo = {
  name: 'foo',
  age: 30,
  major: 'computer science'
};

// for in 문을 이용한 객체 프로퍼티 출력
var prop;
for (prop in foo) {
  console.log(prop, foo[prop]);
} 
/*
name foo
age 30
major 'computer science'
*/

객체 프로퍼티 삭제

delete 연산자를 이용해 객체의 프로퍼티를 삭제할 수 있다.

여기서 주의할 점은 delete 연산자는 객체의 프로퍼티를 삭제할 뿐, 객체 자체를 삭제하지는 못한다.

// 객체 리터럴을 통한 foo 객체 생성
var foo = {
  name: 'foo',
  nickname: 'babo'
};

console.log(foo.nickname); // babo
delete foo.nickname;
console.log(foo.nickname); // undefined

delete foo;
console.log(foo.name); // foo

자바스크립트에서는 존재하지 않는 프로퍼티에 접근할 경우 undefined 값이 출력된다. 

즉, delete 연산자를 통해 삭제된 객체의 프로퍼티는 undefined 값이 출력된다.

delete 연산자는 프로퍼티만을 삭제하기 때문에 foo 객체를 삭제하려고 했던 객체는 삭제되지 않았다.

참조 타입의 특성

자바스크립트에서는 기본 타입인 숫자, 문자열, 불린값, null, undefined를 제외한 모든 값은 객체다.

배열이나 함수 또한 객체로 취급된다.  그리고 이러한 객체는 자바스크립트 참조 타입이라고 부른다.

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

var objA = {
  val: 40
};
var objB = objA;

console.log(objA.val); // 40
console.log(onjB.val); // 40

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

objA 객체를 객체 리터럴 방식으로 생성했다.

여기서 objA 변수는 객체 자체를 저장하고 있는 것이 아니라 생성된 객체를 가리키는 참조값을 저장하고 있다.

변수 objB에 objA 값을 할당하게 되면 objA는 생성된 객체를 가르키는 참조값을 가지고 있으므로 변수 objB에도 이 같은 객체의 참조값이 저장된다.

변수 objB가 가리키는 객체의 val 값을 40에서 50으로 갱신하면 이때 변수 objA도 변수 objB와 동일한 객체를 참조하고 있으므로 값이 50으로 변경된다.

 

객체 비교

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

기본 타입의 경우는 값 자체를 비교해서 일치 여부를 판단하지만, 객체와 같은 참조 타입의 경우는 참조값이 같아야 true가 된다.

 

참조에 의한 함수 호출 방식

기본 타입과 참조 타입의 경우는 함수 호출 방식도 다르다.

기본 타입의 경우는 값에 의한 호출(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(a);
console.log(objA);

/*
200
{ value: 200 }
100
{ value: 200 }
*/

- 본 포스팅은 "인사이드 자바스크립트" 도서를 기반으로 작성한 글입니다.

반응형