책 읽다가 코딩하다 죽을래

자바스크립트 객체 선언, 접근, 메모리저장방식 본문

코딩/자바스크립트

자바스크립트 객체 선언, 접근, 메모리저장방식

ABlue 2021. 7. 22. 00:14

 

이번 시간에는 자바스크립트의 객체의 특징에 대해 설명해보겠다.

자바스크립트의 객체는 Object라 하며 선언은 다음과 같다.

 

 

 


객체의 선언 및 접근


 

 

더보기
const obj1 = {};
const obj2 = new Object();
const ablue = {name:'ablue', age: 26}; // 선언과 초기화를 동시에 하는 법

 

 

객체는 "key" : value로 이루어져 있다.

c언어의 구조체와 자바의 해쉬 맵과 파이썬의 딕셔너리와 비슷하다.

 

그런데 여기서 key는 무조건 string형이며 value는 어떤 타입이든 상관없다.

 

 

console.log(ablue['name']);     //이렇게 배열형태로 데이터에 접근할 수 있다. 주의할 점은 배열의 인덱스는 String타입으로 줘야한다. name으로 주면 undefined가 뜬다.
ablue['age'] = true;     //이런식으로 데이터를 설정할때도 쓰인다.

console.log(ablue.name);		// 배열형태가 아닌 c언어처럼 .(닷) 을 붙여 해당 속성에 접근할 수 있다.
ablue.name = "홍길동";

 

 

 


객체의 메모리 저장 방식


 

더보기

자바스크립트는 8가지 기본 자료형을 지원한다.

 

1. 정수, 부동 소수점을 저장하는 숫자형(Number) : -(2^53-1) ~ (2^53-1)까지 지원
Number의 범위를 넘어서는 숫자를 저장하는 BigInt형
문자열을 저장하는 문자형(String)
논리 값 (true/false. boolean형 )
값이 할당되지 않음을 나타내는 독립 자료형 undefined
값이 존재하지 않음을 나타내는 독립 자료형 null
복잡한 자료구조를 저장하는 데 쓰는 객체형
고유 식별자를 만들 때 쓰는 심볼형  

 

여기서 객체형을 제외한 다른 데이터 타입들은 원시형이다

원시형이란 말은 오직 하나의 값만 저장되는 것이다.

 

오직 하나의 값만 저장하게 되니 실제 메모리에선

 해당 사진의 출처는 인프런 정재남 선생님의 JS Flow 강의에 있습니다.

강의 보러 가기 [클릭]

 

이런 식으로 저장이 된다.

변수 값을 사용할 때마다 해당 변수명을 찾아 값이 저장된 주소를 확인하고

그 주소에 찾아가 실제 값을 읽는다.

 

 

let a = 10;
let b = a;

console.log(a === b) // true

a = 5;
console.log(b);		 // 10
console.log(a === b) // false

 

그래서 b에다 a값을 대입하면 똑같아진다.

왜냐하면 메모리 상에서 b가 가리키는 값과 a가 가리키는 값은 똑같기 때문이다.

 

하지만 a와 b가 서로 같은 곳을 가리키는 것은 아니기 때문에

a와 b 중 어느 하나의 값이 달라진다 해서 나머지 변수는 달라지진 않는다.

모든 원시형 데이터 타입은 이런 특징을 갖는다.

 

 

그런데 객체는 다른 방식으로 메모리에 저장된다.  

 

 

 

 

 객체가 초기화되면 주소 값이 참조된 곳에 값이 들어있는 것이 아니라

객체의 속성 값이 저장된 주소들의 집합체의 주소가 들어있다.

 

 

 

그래서 객체의 객체를 대입하면

원시 데이터 타입처럼 메모리 사용량이 2배가 되진 않는다.

이렇게 같은 곳(1011번)을 가리키게 된다.

 

 

var obj = {a:1, b:'b'};
var obj2 = obj;
obj2.a = 10;
console.log(obj.a);		// 10

 

그래서 한쪽의 객체의 속성값을 초기화하면 반대쪽 객체의 해당 속성값도 달라진다.

왜냐하면 서로 같은 곳을 가리키기 때문이다.

 

그러면 같은 곳을 가리키지 못하게 만들면서 복사하는 방법은 

... (sprread operator 펼침연산자) 을 사용한다.

 

var obj3 = ...obj;
obj3.a = 10;
console.log(obj.a);		// 1

 

우리는 이런 복사 방식을 얕은 복사(shallow copy)라고 부른다.

var obj3 = obj;는 같은 곳을 가리키게 만드니 깊은 복사(deep copy)다.

 

펼침 연산자는 배열에도 쓰인다.

배열에도 쓰인다는 것은 배열도 객체의 메모리 저장 방식을 따른다.

const ary = [...ary2];

 

또는 Object의 assign 메소드로 얕은 복사가 가능하다.

 

const user = {name:'ablue', age:26};
const user2 = {};
Object.assign(user2, user);

 

 

또한 이런 객체의 메모리 저장 방식 때문에 이런 것도 가능하다.

 

 

const obj = {a:1, b:'b'};

obj.b = 'c';

 

 분명 const로 상수 취급했는데 속성값을 초기화할 수 있다.

왜냐하면 속성값을 다르게 했다 해도 obj의 주소값이 가리키는 속성값이 담긴 집합체가 담겨있는 주소값이 달라지는 것이 아니기 때문이다.

이 말이 되게 어렵게 느껴지는게 그림으로 설명해보자면 이렇다.

 

 

 

obj.b의 새로운 값으로 초기화하면 obj의 주소값(413)은 달라지지않고 b의 해당하는 주소값(1013)만 달라지게 된다. 즉 자바스크립트 엔진에선 obj.c가 초기화된다고해도 똑같다고 생각하는 것이다.

 

const는 주소값만 달라지지 않으면 초기화되었다고 판단하지 않는다.

 

 

 

const obj = {name:'ablue', age:26};
obj = {name:'바뀐이름', age:27};		// Uncaught TypeError: Assignment to constant variable.

 하지만 전부를 초기화하는 것은 주소값이 달라져서 가리키는 것이 달라지기 때문에 오류가 일어난다.

 

const ary = [1,2,3];
ary[0] = 2;	// 오류가 일어나지 않음
ary = [4,5,6]; // Uncaught TypeError: Assignment to constant variable.

배열도 마찬가지이다. 

 

 

자바스크립트엔진은 값이 달라졌는지 않았는지 판단할 때 Object is 비교알고리즘을 통해 판단하는데

이 사고방식에 대해 자세하게 알고싶다면 JS 공식 문서의 Object is 를 읽어보자

 

 

 

 

Object is 공식문서 보러 가기[클릭]

 

 


객체의 순차 접근


 

더보기

객체의 순차 접근은 for .. in 과 for .. of 가 있다.

 

 

for .. in

//for (key in obj)
const ablue = {age: 26, hobby:'coding', dream:'FrontEnd'};
for(key in ablue){      //향상된 for구문과 같다 
    console.log(key);
}

// age		//그러나 for..in구문은 객체의 key값엔 접근가능하나 key의 value에는 접근할 수 없다. 접근할려면 ablue[key]를 사용해야한다.
// hobby
// dream

for(key in ablue){
    console.log(ablue[key]);
}

// 26
// coding
// FrontEnd

 

for .. of 

 

// for(value of iterable) 순서가 있는 객체를 출력할 때 쓴다
const array = [1,2,4,5];
for(value of array){
    console.log(value);		// 1 2 4 5
}