TIL) JavaScript의 Object - 2

Solmii·2020년 5월 30일
0

JavaScript

목록 보기
16/24
post-thumbnail

Object vs Array

🖍 object literal(객체 리터럴)

객체는 { } 만 사용하면 다른 데이터 타입(string, number, array 등..)처럼 변수에 저장할 수 있다. 이렇게 { } 모양으로 생긴 객체를 객체 리터럴이라고 부른다!

객체는 순서가 없는 데이터의 모음이고, 배열은 순서가 있는 데이터의 모음이다.

순서가 없다에서 순서는 물론 index를 말한다.

let arr = ['떡볶이', '맛있어', '시금치', '맛없어'];

arr 의 요소가 차례대로 추가되었고, index를 통해 각 순서에 맞는 데이터를 호출할 수 있다.

arr[0] = 떡볶이 arr[1] = 맛없어

반면에 객체는 키(key): 값(value) 쌍으로 된 데이터의 모음으로써 순서가 뒤바껴도 아무 상관이 없다.

배열처럼 순서대로 index로 접근하는게 아니라 key로 접근하기 때문에!

(key는 property name, value는 property value라고도 부른다.)


key (property name)

key는 마치 특정 값을 갖고 있는 변수같은 역할을 한다.
해당 키로 프로퍼티에 어떤 값이 저장되었는지 알 수 있기 때문이다.

let name = "solmi"
console.log(name); // solmi

let myIntro = {
	name: "solmi",
	age: 26,
}
console.log(myIntro.name); // solmi

key의 value에는 string, number 뿐만 아니라 function, object도 넣을 수 있다.

객체의 key 이름에는 스페이스, 한글, 특수문자 등이 들어갈 수 있다.
(변수(variable) 선언할 때는 불가능한 일이다!)

let difficult = {
	33: '숫자 형식도 되네',
  'my name': 'solmi', // 스페이스가 들어가면 ''로 묶기
  color: 'silver',: '한글인 키는 따옴표가 없어도 되는군!!',
  '!키': '느낌표 있는 키는 따옴표가 필요하군', // 특수문자가 들어가면 ''로 묶기
  $special: '$는 없어도 되는군' // $는 ''로 묶지 않아도 됨
};

프로퍼티 접근 (Property accessors)

프로퍼티에 접근하는 방법은 dot . 으로 접근하는 법과, 대괄호 [ ] 로 접근하는 법이 있다.

console.log(difficult.color);

사실 key를 알고 있으면 dot .으로 접근하는 것이 제일 편하다!!

( dot .은 key로 바로 접근할 때 사용)


console.log(difficult['color']);

대괄호 [ ] 로 접근할 수도 있다!

이 때는 key 이름을 ' ' 로 감싸서 작성해야 한다.


console.log(difficult.my name); // error
console.log(difficult['my name']);

스페이스가 포함된 키는 무조건 대괄호 [ ] 로 접근해야 한다.


console.log(difficult.33); // error
console.log(difficult['33']);

숫자로 된 key는 dot . 으로 바로 접근할 수 있을 것 같지만 대괄호 [ ] 로 접근해야 한다.


let name = '키';
console.log(difficult[name]);
console.log(difficult.name); // undefined

변수에 key 이름이 저장되어 있으면, 변수로도 프로퍼티에 접근할 수 있다.

이 때, dot . 으로 접근하면 undefined 가 출력된다.

(dot . 으로 접근한다는 것은 실제 그 key의 이름을 쓸 때를 말함)


프로퍼티 할당

let difficult = {
	33: '숫자 형식도 되네',
  'my name': 'solmi', // 스페이스가 들어가면 ''로 묶기
  color: 'silver',: '한글인 키',
  '!키': '느낌표 있는 키는 따옴표가 필요하군', // 특수문자가 들어가면 ''로 묶기
  $special: '$는 없어도 되는군' // $는 ''로 묶지 않아도 됨
};

객체에 이미 존재하는 key에 다시 한 번 value를 할당하면 value가 교체(수정)된다.

difficult['키'] = '나는 값이 바뀐 키';
console.log(difficult['키']); // 한글인 키 -> 나는 값이 바뀐 키

difficult.color = 'pink';
console.log(difficult.color); // silver -> pink

이전에 없던 key로 접근해서 vlaue를 입력하면, 새로운 프로퍼티가 추가된다.

console.log(difficult.new); // undefined => 아직 없던 key에 접근하면 프로퍼티를 추가할 준비는 되어있지만 value가 없기 때문에 error가 아닌 undefined
difficult.new = '새로 추가된 프로퍼티';
console.log(difficult.new); // 새로 추가된 프로퍼티

🙋🏻‍♀️ const로 선언된 변수와 프로퍼티 할당

객체를 const로 선언했을 때 생기는 일이다.

const a = 1;
a = 2; // error

const로 선언된 변수는 값은 당연히 수정할 수 없다. 위 예시와 같이 error가 발생한다.

마찬가지로, const로 선언된 변수에 객체를 할당한 후, 새로운 객체를 다시 할당하면 error가 발생한다.

const mutableObj = { // 객체 할당
  name: '객체'
};

mutableObj = { // 객체 재할당? error
   name: '수정'
}

그런데, mutableObj 의 프로퍼티에 접근해서 내용을 수정하거나, 프로퍼티를 추가 하는 것은 error가 나지 않는다.

mutableObj.name = '수정'; // 프로퍼티 수정
mutableObj.type = 'Object 타입'; // 프로퍼티 추가

console.log(mutableObj); // { name: '수정', type: 'Object 타입' }

🤷🏻‍♀️ 왜?

객체를 변수에 저장하면 객체 리터럴 자체가 저장되는 것이 아니라 reference가 저장되기 때문!
( 객체의 크기는 너무 커서 하나의 메모리에 담기지 않고, 객체를 가르키는 reference가 메모리에 저장되기 때문이다!)

예를들어, 텍스트를 변수에 저장하면...

const a = '안녕';
const b = '안녕';
console.log(a === b); // true

이 둘은 값이 같으므로 당연히 true이다.
텍스트는 메모리에 텍스트 자체가 저장되기 때문에 안녕안녕 을 비교하는 꼴이다.

const hiObj = { 
  name: '안녕' 
};
const helloObj = {
  name: '안녕'
};
console.log(hiObj === helloObj); // false

하지만, 객체는 hiObjhelloObj 랑 똑같이 생겼어도 false라고 출력된다.

그 이유는 변수에 객체를 저장할 때, 객체 리터럴 자체를 그대로 저장하는것이 아니기 때문!
객체가 담긴 어느 메모리의 reference 즉, 해당 객체의 메모리 주소를 저장한다.

hiObjname: '안녕' 이라는 값을 담고 있다고 생각했지만,
사실 진짜 담겨있는 값은 메모리 주소인 reference 인 것!

물론 hiObj 를 불러오는 과정에서 담고있는 값인 메모리 주소를 툭 뱉는게 아니라, 해당 메모리 주소에 저장된 데이터를 반환해주기 때문에 눈에 보이는 데이터는 똑같지만, 실제 hiObjhelloObj 의 값은 다르다.

console.log(hiObj === helloObj); // false
console.log(hiObj.name === helloObj.name); // true

그래서 이렇게 객체를 담은 변수 끼리 비교하면 항상 false가 나오고,

객체 내부의 프로퍼티 값을 비교하면 true / false 여부를 판단할 수 있다.


const mutableObj = { // 객체 할당
  name: '객체'
};

mutableObj = { // 객체 재할당? error
   name: '수정'
}

그렇다면 const로 선언된 객체의 name 프로퍼티를 수정하려면 어떻게 해야 할까?

mutableObj.name = '수정!!';

이렇게 mutableObj.name 에 직접 접근해서 수정하면 된다.

const 로 선언된 mutableObj의 reference가 바뀌는 것이 아니라, reference가 가리키고 있는 객체 내부의 실제 프로퍼티 메모리에 접근하여 값을 수정했기 때문에 const 로 선언된 객체의 프로퍼티를 수정할 수 있는 것이다.


Method(메서드)

제일 많이 쓰는 함수인 console.log(); .....

이녀석도 사실은 객체이다! (어디에서나 접근이 가능하니 global object)

console 다음에 dot . 으로 log 라는 프로퍼티에 접근했고,

log 라는 key의 value는 console 창에 log 를 띄우는 함수인 것이다.

이렇게 객체에 저장된 값이 함수 일 때, 이 함수를 Method(메서드)라고 부른다.

👉 즉, logconsole 이라는 객체의 메서드인 것!!!

🤷🏻‍♀️ 우리가 직접 객체에 method를 정의하고 싶다면?

let methodObj = {
  do: function() { // 이렇게 메서드를 정의하고
    //대충 실행하고 싶은 함수
  }
}
methodObj.do(); // 이렇게 호출하면 된다!

Nested Object (중첩된 객체)

우리가 흔히 보는 객체는 거의 중첩되어 있다.

프로퍼티 값이 객체일 수도 있고, 프로퍼티 값인 배열의 요소가 객체일 수도 있다.

let nestedObj = {
  type: {
    year: '2019',
    'comment-type': [{
      name: 'simple'
    }]
  }
}

위와 같은 코드에서 simple 을 가져오려면?

console.log(nestedObj.type['comment-type'][0].name); // simple
  1. nestedObj.type : year, comment-type이 있는 객체
  2. nestedObj.type['comment-type'] : 요소가 1개(객체)인 배열
  3. nestedObj.type['comment-type'][0] : 배열의 첫 번째 요소인 객체를 가져온다.
  4. nestedObj.type['comment-type'][0].name 드디어 'simple'에 접근!
profile
하루는 치열하게 인생은 여유롭게

0개의 댓글