[JavaScript] 내가보려고 작성하는 벨로그 12

Rookie·2022년 4월 3일
0
post-thumbnail

26-1. 다시 나타난 Object

여러 분의 이해를 위해 Object 강의 하나를 더 추가했습니다. 개념이 다시 정리되기를 바라겠습니다!

객체는 다른 데이터 타입(텍스트, 숫자, 배열 등..)처럼 변수에 저장할 수 있습니다. {} 만 사용하면 되는데요, 이렇게 {} 으로 생긴 모양의 객체를 object literal(객체 리터럴)이라고 부릅니다.

hello 라는 변수에 빈 객체를 할당하였습니다.

let hello = {};
let hello = {};
객체는 순서가 없는 데이터의 모음입니다.

반대로 순서가 있는 데이터는 배열입니다.

let arr = ['고양이', '귀여워', '멍멍이', '좋아'];
let arr = ['고양이', '귀여워', '멍멍이', '좋아'];
arr 의 요소가 차례대로 추가된 것이고 index 는 0부터 시작합니다.

arr[0] 은 '고양이' 이고, arr[1] 은 '귀여워' 입니다.

객체는 키(key)-값(value) 쌍으로된 데이터의 모음으로써 순서가 뒤 바뀌어도 아무 상관이 없습니다. 배열처럼 순서대로 index 로 접근하는게 아니라 키로 접근하기 때문입니다.

key는 property name이라고도 하며, value는 property value라고도 말합니다.

이전 강의에서는 프로퍼티명, 프로퍼티값으로 불렀으니 이번에는 키, 값으로 부르겠습니다.

키는 마치 특정 값을 갖고 있는 변수같은 역할을 합니다. 해당 키로 프로퍼티에 어떤 값이 저장돼 있는지 알 수 있습니다. 키의 값에는 텍스트, 숫자 뿐만 아니라 함수, 객체도 넣을 수 있습니다.

이전 강의에서 언급하지 않았던 키에 대해 얘기해보겠습니다.

let difficult = {
  'my name': 'boong',
  color: 'silver',: '한글인 키는 따옴표가 없어도 되는군!!',
  '!키': '느낌표 있는 키는 따옴표가 필요하군',
  $special: '$는 없어도 되는군'
};
let difficult = {
  'my name': 'boong',
  color: 'silver',: '한글인 키는 따옴표가 없어도 되는군!!',
  '!키': '느낌표 있는 키는 따옴표가 필요하군',
  $special: '$는 없어도 되는군'
};

객체의 키에는 스페이스, 한글, 특수문자 등이 들어갈 수 있습니다. 변수(variable) 선언할 때는 할 수 없었던 표현입니다. color 와 같이 키에 특수문자가 없으면 따옴표를 생략하고 쓸 수 있습니다.

다양한 프로퍼티 명을 넣어보고 스크립트 오류가 없는지 확인해보세요.


26-2. 프로퍼티 접근

이전 강의 Assignment가 사실 더 어려웠습니다. 그 문제를 풀기 위해선 프로퍼티 접근에 익숙해야 했습니다.

이번 시간에 익숙해질 수 있도록 다시 한 번 훑어보겠습니다. 접근은 dot(.)으로 접근하는 방법과, [] 대괄호로 접근하는 법이 있었습니다.

let difficult = {
  33: '숫자 형식도 되네',
  'my name': '스페이스 포함 가능',
  color: 'silver',: '한글인 키는 따옴표가 없어도 되는군!!',
  '!키': '느낌표 있는 키는 따옴표가 필요하군',
  $special: '$는 없어도 되는군'
};
let difficult = {
  33: '숫자 형식도 되네',
  'my name': '스페이스 포함 가능',
  color: 'silver',: '한글인 키는 따옴표가 없어도 되는군!!',
  '!키': '느낌표 있는 키는 따옴표가 필요하군',
  $special: '$는 없어도 되는군'
};
console.log(difficult.color);
console.log(difficult.color);

사실 키만 알고 있으면 dot(.)으로 접근하는 것이 제일 편합니다. dot(.)은 키로 바로 접근할 때 사용하는 것입니다. dot으로 접근할 때는 따옴표 없이 키를 바로 써줘야 합니다.

그런데 [] 대괄호로 접근할 수도 있었죠!

console.log(difficult['color']);
console.log(difficult['color']);
대괄호로 접근 하기 위해서는, 키 이름을 따옴표로 감싸서 작성해줘야 합니다.

한번 주석을 풀고 실행해보세요!

console.log(difficult.my name);
console.log(difficult.my name);
왠지 모르겠지만, 실행을 안 해봐도 오류가 날 것만 같습니다.

이렇게 스페이스가 포함된 키는 대괄호로 접근하면 됩니다.

console.log(difficult['my name']);
console.log(difficult['my name']);
아래의 코드는 왠지 될 것 같지만 되지 않습니다.

console.log(difficult.33);
console.log(difficult.33);
숫자로 된 키는 대괄호로 접근해야 합니다.

console.log(difficult['33']);
console.log(difficult['33']);
어떤 것은 dot(.)접근 가능, 어떤 것은 대괄호만 가능..

다 외워야 하나요? 아닙니다.

어차피 코딩할 때 잘 못 접근하면 오류가 뜨기 때문에 지금 모르셔도 괜찮습니다. 오류 뜨면 그 때 오류 메시지를 확인하고 수정하면 됩니다! 이렇게 다양한 형태로 키 이름을 지을 수 있다는 것만 알아주세요.


26-3. 변수로 프로퍼티 접근하기

let name = '키';
console.log(difficult[name]);
let name = '키';
console.log(difficult[name]);
변수에 키 이름이 저장되어있으면, 변수로도 프로퍼티에 접근 가능합니다.

이때 dot(.) 다음에 변수명을 넣어서 프로퍼티에 접근이 가능 할까요?

console.log(difficult.name);
console.log(difficult.name);
직접 실행 해봅시다. 뭐라고 나오나요? undefined 입니다.

dot(.)으로 접근한다는 뜻은 실제 키이름을 쓸 때입니다.

'name' 이라는 키가 있었으면 그에 해당하는 프로퍼티에 접근할 수 있었겠지만, 존재하지 않기 때문에 undefined 가 나온것입니다. 변수로 접근할 때는 항상 대괄호로 접근해야 합니다.


26-4. 프로퍼티 할당

difficult[name] = '값 바꾼다';
console.log(difficult[name]);

difficult.color = '색깔';
console.log(difficult.color);

console.log('생성전: ' + difficult.new);
difficult.new = '새로 추가된 프로퍼티';
console.log('생성후: ' + difficult.new);
difficult[name] = '값 바꾼다';
console.log(difficult[name]);

difficult.color = '색깔';
console.log(difficult.color);

console.log('생성전: ' + difficult.new);
difficult.new = '새로 추가된 프로퍼티';
console.log('생성후: ' + difficult.new);
객체에 이미 키가 존재하는데, 다시 한 번 할당하면 값이 교체(수정)됩니다.

이전에 없던 키로 접근하면, 새로운 프로퍼티가 추가 됩니다.

아직 없던 키에 접근하면 프로퍼티를 추가할 준비는 되어있지만, 값이 없습니다

console.log(difficult.newProperty);
console.log(difficult.newProperty);
어떤 값이 나오나요? 네, undefined 입니다.

아직 difficult 라는 객체에 newProperty 프로퍼티가 없기 때문에 undefined 입니다. 아래는 없었던 키에 값을 바로 입력해서 프로퍼티를 추가하는 방법입니다.

difficult.realNewProperty = '추가 됐다';
difficult.realNewProperty = '추가 됐다';
객체의 특별한 점을 알려드리겠습니다.

객체를 const 로 선언했을 때 알쏭달쏭한 현상이 일어납니다.

const a = 1;
a = 2;
const a = 1;
a = 2;

const 로 선언된 변수는 값을 절대 수정할 수 없었습니다. a = 2; 를 시도하면 자바스크립트 오류가 납니다.

그런데 const 로 선언된 변수에 객체를 다시 할당하면 오류가 생기지만, 그 객체에 프로퍼티를 추가하거나 수정하는 것은 가능합니다.

const mutableObj = {
  name: '객체'
};

mutableObj = {
   name: '수정'
}
const mutableObj = {
  name: '객체'
};

mutableObj = {
   name: '수정'
}

변수 mutableObj 자체에 객체를 재 할당하는 것은 불가능 합니다. 실행해보면 자바스크립트 오류가 납니다.

mutableObj.name = '수정';
mutableObj.type = 'Object 타입';
mutableObj.name = '수정';
mutableObj.type = 'Object 타입';
그렇지만 프로퍼티에 접근해서 내용을 수정하거나, 프로퍼티를 추가하는 것은 에러가 나지 않습니다.


26-5. Method (메서드)

객체에 저장된 값이 함수일 때, 메서드라고 부릅니다.

console.log();
console.log();
console.log() 도 형태를 보니 객체인가 봅니다. 자바스크립트 어디에나 접근이 가능 했으니 global 객체입니다. console 다음에 dot(.)으로 프로퍼티를 접근했고, log 라는 키의 값은 함수인 것 같습니다. log는 console 이라는 객체의 메서드입니다. 객체에 메서드를 정의하려면 아래와 같이 할 수 있습니다.

let methodObj = {
  do: function() {
    console.log('메서드 정의는 이렇게');
  }
}
let methodObj = {
  do: function() {
    console.log('메서드 정의는 이렇게');
  }
}

호출 방법은 아래와 같습니다!

methodObj.do();


26-6. 중첩된 객체 (Nested Object)

실무에서 사용되는 객체는 거의 중첩되어 있습니다. 프로퍼티 값이 객체일 수도 있고, 프로퍼티 값인 배열의 요소가 객체일 수도 있습니다.

let nestedObj = {
type: {
year: '2019',
'comment-type': [{
name: 'simple'
}]
}
}
let nestedObj = {
type: {
year: '2019',
'comment-type': [{
name: 'simple'
}]
}
}
위에서 'simple' 을 출력하려면 어떻게 해야할까요?

console.log(nestedObj.type['comment-type'][0].name);
console.log(nestedObj.type['comment-type'][0].name);
컴퓨터는 왼쪽에서 오른쪽으로 해석한 다는 것을 명심하고 이해해주세요.

항상 왼쪽에 직접 코드를 써야 한다는 것을 잊지 말아주세요!!

nestedObj.type 는 year, comment-type 이 있는 객체입니다
nestedObj.type['comment-type'] 는 요소 1개인 배열입니다.
nestedObj.type['comment-type'][0] 첫 번째 요소인 객체를 가져옵니다.
nestedObj.type['comment-type'][0].name 드디어 'simple'에 접근!


26-7. 객체는 reference로 저장된다.

조금 어려운 이야기를 시작하려고 합니다!

객체는 reference가 저장됩니다.. 음 무슨말일까요?

객체를 변수에 저장하면 객체 자체가 저장되는 것이 아니라 reference가 저장됩니다.

반대로, 텍스트는 변수에 저장하면 텍스트 자체가 저장됩니다. 그래서 서로 같은 텍스트를 비교연산 하면 서로 값이 같으므로 true 입니다.

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

그런데 아래의 객체는 생긴 모양이 아예 똑같은데 false 라고 출력됩니다.

const hiObj = { 
  name: '안녕' 
};
const helloObj = {
  name: '안녕'
};
console.log('객체비교 =>', hiObj === helloObj);
const hiObj = { 
  name: '안녕' 
};
const helloObj = {
  name: '안녕'
};

console.log('객체비교 =>', hiObj === helloObj);
그 이유는 객체는 변수에 저장할 때, 객체 자체를 그대로 저장하는 것이 아니기 때문입니다. 객체가 담긴 어느 메모리의 reference 를 저장하기 때문입니다.

hiObj 가 갖고 있는 진짜 값은 메모리 주소인 reference입니다. 하지만 hiObj 를 불러올 때 메모리 주소를 반환하는 것이 아니라, 해당 메모리에 저장된 데이터를 반환해 줍니다.

그래서 눈에 보이는 데이터는 똑같지만, hiObj 와 helloObj 가 갖고 있는 진짜 값은 다른 것입니다.

console.log('객체비교 =>', hiObj === helloObj);
console.log('객체값비교 =>', hiObj.name === helloObj.name);
console.log('객체비교 =>', hiObj === helloObj);
console.log('객체값비교 =>', hiObj.name === helloObj.name);
그래서 객체를 담은 변수를 비교하면 서로 같지 않다고 나옵니다. 그러나 객체 내부의 프로퍼티 값이 텍스트일 경우는, 텍스트를 비교하게 되어 서로 같음 / 다름 여부를 판단할 수 있습니다.

다시 한 번 const 로 선언된 객체를 볼까요.

const mutableObj = {
  name: '객체'
};

mutableObj = {
   name: '수정'
}

mutableObj.name = '수정 됩니다!';
const mutableObj = {
  name: '객체'
};

mutableObj = {
   name: '수정'
}

mutableObj.name = '수정 됩니다!';
const 로 선언된 변수는 절대 값이 바뀌면 안 되는거 아시죠? 그래서 mutableObj 에 새로운 객체를 할당하면 오류가 납니다. 왜냐면 새로운 메모리 주소(reference)로 수정을 시도하기 때문이죠.

하지만 mutableObj.name 로 프로퍼티에 접근해서 수정할 수 있습니다. mutableObj 가 저장된 reference가 바뀌는 것이 아니라 객체 내부의 프로퍼티 값이 수정되는 것이라 수정이 되는 것이었 답니다....

profile
노력형 잡캐입니다

0개의 댓글