TIL 29 | Javascript - Objects

hyounglee·2020년 8월 20일
1

JavaScript

목록 보기
17/46
post-thumbnail

Object (객체)

위의 표에 나타난 데이터를 자바스크립트 언어로 구현한다면 아래와 같이 저장해야 한다.

let plan1Name = "Basic";
let plan1Price = 3.99;
let plan1Space = 100;
let plan1Data = 1000;
let plan1Pages = 10;
let plan2Name = "Professional";
let plan2Price = 5.99;
let plan2Space = 500;
let plan2Data = 5000;
let plan2Pages = 50;
let plan3Name = "Ultimate";
let plan3Price = 9.99;
let plan3Space = 2000;
let plan3Data = 20000;
let plan3Pages = 500;

이런식으로 해당 플랜에 대한 변수 나열이 필요한데, 이 역시 데이터가 훨씬 늘어난다고 생각한다면 코드도 길어지고 관리하는데 어려움이 생긴다. 이러한 유형의 데이터는 Object(객체)로 표현할 수 있다. 위 데이터를 Object에 맞게 표현하면 아래와 같다.

객체 선언

var 객체이름 = {
    property이름1: property값,
    property이름2: Property값
};

객체는 {}(중괄호) 로 감싸져 있고, 콜론으로 구분된 이름/값 쌍들이 쉼표로 분리된 목록의 형태이다. 다시 말해 객체는 이름과 값으로 구성된 프로퍼티들의 집합이다. 위 예시와 같이 프로퍼티 이름은 중복될 수 없다.

위 표의 plan1의 객체를 만들자면 아래와 같다.

let plan1 = {
  name: "Basic",
  price: 3.99,
  space: 100,
  transfer: 1000,
  pages: 10
};

객체를 만드는데 꼭 알아야 할 규칙

  • property 이름은 중복될 수 없다.
  • property이름과 property값 사이에 **:(콜론)**으로 구분한다.
  • property를 추가할 때는 **,(쉼표)**를 붙여준다.
  • property 값에는 어느 type이나 가능하다(string, number, array, object, function..)

프로퍼티 접근

해당 객체의 property값을 접근하고 싶을 때는 아래와 같다.

  1. 객체명.프로퍼티명 : 마침표( . ) 연산자를 사용하며, 접근하려는 객체명은 왼쪽에, 프로퍼티명은 오른쪽에 위치합니다.
  1. 객체명["프로퍼티명"] : 대괄호( [] )를 사용하여, 접근하려는 객체명은 왼쪽에, 프로퍼티명은 쌍따옴표( "" )와 함께 대괄호 안에 작성합니다.
let plan1 = {   
  name: "Basic"
};

console.log(plan1.name);
console.log(plan1["name"]);

보통은 마침표(.)로 접근하는 방식이 편하지만, 대괄호 표현 안에는 변수가 들어갈 수 있다는 차이점이 있다. 예를 들어 plan1 객체의 name이라는 프로퍼티에 접근하고 싶을 때, 아래와 같이도 할 수 있다.

let plan1 = {   
  name: "Basic"
};

let propertyName = "name";

console.log(plan1[propertyName]);

객체의 객체의 배열의 객체

let objData = {
  name: 50,
  address: { 
    email: "gaebal@gmail.com",
    home: "위워크 선릉2호점"
  },
  books: {
    year: [2019, 2018, 2006],
    info: [{
      name: "JS Guide",
      price: 9000
    }, {
      name: "HTML Guide",
      price: 19000,
      author: "Kim, gae bal"
    }]
  }
};

objData라는 객체안에 name, address, books라는 property가 있다. books에 또 객체가 할당되었다.

위의 데이터에서 "HTML Guide"에 접근하고 싶을 때는 아래와 같이 해주면 된다.

let bookName = objData.books.info[1].name;
console.log(bookName);

Object +ɑ

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

// hello라는 변수에 빈 객체를 할당한다.
let hello = {};

객체는 순서가 없는 데이터의 모음이다?

배열에 index 즉 순서가 있는 것과는 달리 객체에는 데이터의 순서가 없다.

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

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

key는 property name이라고도 하며, value는 property value라고도 한다.

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

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

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

프로퍼티 접근 2

앞서 말했듯이 접근은 **dot . **으로 접근하는 방법과, 대괄호 [] 로 접근하는 법이 있다. **dot . ** 은 키가 바로 접근할때만 사용한다.

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

1. console.log(difficult.color);

사실 키만 알고 있으면 dot(.)으로 접근하는 것이 제일 편하다. dot으로 접근할 때는 따옴표 없이 키를 바로 써줘야 한다. 대괄호로 접근하려면 ['color'] 과 같이 키 이름을 따옴표로 감싸서 작성해야 한다.

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

스페이스가 포함된 키는 반드시 대괄호로 접근해야 한다. dot으로 접근하면 오류가 난다.

3. console.log(difficult['33']);

숫자로 된 키는 반드시 대괄호로 접근해야 한다. dot으로 접근하면 오류가 난다.

프로퍼티 접근 3 - 변수

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

변수에 키 이름이 저장되어있으면, 변수로도 프로퍼티에 접근이 가능하다. 변수로 접근할 때는 항상 대괄호로 접근해야 한다.** dot . ** 으로 접근한다는 것은 실제 키이름을 쓸 때 뿐이다.

프로퍼티 할당

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

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

console.log('생성전: ' + difficult.new);
difficult.new = '새로 추가된 프로퍼티';
console.log('생성후: ' + difficult.new);

// 값 바꾼다
// 색깔
// 생성전: undefined
// 생성후: 새로 추가된 프로퍼티

객체에 이미 키가 존재하는데, 다시 한 번 할당하면 값이 교체(수정)된다. 이전에 없던 키로 접근하면, 새로운 프로퍼티가 추가된다. 아직 없던 키에 접근하면 프로퍼티를 추가할 준비는 되어있지만, 값이 없다고 나온다( undefined ).

아래는 없었던 키에 값을 바로 입력해서 프로퍼티를 추가하는 방법이다.

difficult.realNewProperty = '추가 됐다';

객체와 const

const a = 1;
a = 2;

기본적으로 const로 선언된 변수는 값을 절대 수정할 수 없다. 위 코드에서 a = 2;를 시도하면 자바스크립트 오류가 난다. 하지만 객체를 const로 선언했을때 신기한 현상이 나타난다.

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

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

mutableObj = {
   name: '수정'
}

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

mutableObj.name = '수정';
mutableObj.type = 'Object 타입';

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

Method(메서드)

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

console.log();

console 도 어디에서나 접근이 가능한 global 객체이다. console 다음의 dot . 으로 프로퍼티에 접근하고, log 라는 키의 값이 함수이다. 즉 logconsole 이라는 객체의 메서드이다.

객체에 메서드를 정의하려면 아래와 같이 할 수 있다.

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

호출 방법은 아래와 같이!

methodObj.do();

중첩된 객체 (Nested Object)

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

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

위에서 'simple'을 출력하려면?

console.log(nestedObj.type['comment-type'][0].name);

컴퓨터는 왼쪽에서 오른쪽으로 해석한다는 것을 명심하고 이해해야한다!

객체는 reference로 저장된다.

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

텍스트는 변수에 저장하면 텍스트 자체가 저장된다. 그래서 같은 텍스트면 서로 값이 같으므로 true이다.

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

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

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

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

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

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

console.log('객체비교 =>', hiObj === helloObj); // 객체비교 => false
console.log('객체값비교 =>', hiObj.name === helloObj.name); // 객체값비교 => true

그래서 객체를 담은 변수를 비교하면 서로 같지 않다고 나온다. 그러나 객체 내부의 프로퍼티 값이 텍스트일 경우는, 텍스트를 비교하게 되어 서로 같음/다름 여부를 판단할 수 있다.

프로퍼티로 접근하여 수정하자! (객체와 const)

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

// 값 수정 시도. 오류남
mutableObj = {
   name: '수정'
}

mutableObj.name = '수정 됩니다!';

const로 선언된 변수는 절대 값이 바뀌면 안되기 때문에 mutableObj에 새로운 객체를 할당하면 오류가 난다. 왜냐면 새로운 메모리 주소(reference)로 수정을 시도하기 때문이다.

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

profile
(~˘▾˘)~♫❝ 쉽게만 살아가면 재미없어 빙고 .ᐟ ❞•*¨*•.¸¸♪

0개의 댓글