jiho_bae
Go devlog
jiho_bae
전체 방문자
오늘
어제
  • 분류 전체보기 (158)
    • JavaScript (38)
      • theory (34)
      • vanilla (4)
    • HTML & CSS (2)
    • Browser (3)
    • CS (6)
      • linux (1)
      • shell (2)
      • compiler (2)
    • DS & Algorithm (87)
      • theory (5)
      • basic (7)
      • programmers (30)
      • baekjoon (45)
    • Design Pattern (2)
    • Error (4)
    • Git & Github (4)
    • Tools (1)
    • 부트캠프 (4)
    • Small Tips (2)
    • Java (3)
    • test (1)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • 깃 이전 커밋에서 새 브랜치 만들기
  • 카카오 코딩테스트 양궁대회 nodeJS
  • 외벽 점검 javascript
  • 13460 javascript nodejs
  • 가사 검색 자바스크립트
  • 프로그래머스 숫자카드나누기 javascript
  • safari Date format NaN
  • 자바스크립트 커링
  • 백준 자바스크립트 입력 템플릿
  • 리코쳇 로봇 javascript
  • 자바스크립트 sort는 왜 그모양일까
  • 리액트 프로젝트 디버깅하기
  • 계수정렬 자바스크립트
  • fetch 취소하기
  • 퀵정렬 자바스크립트
  • 자바스크립트 배열의 특수함
  • 1753 최단경로 javascript
  • javascript use strict
  • 병합정렬 자바스크립트
  • 백준 17406 nodeJS
  • 대충만든자판 javascript
  • 덧칠하기 javascript
  • 자바스크립트 이벤트 위임
  • JavaScript
  • 25632 소수 부르기 게임
  • 억억단을 외우자 javascript
  • 자바스크립트 비동기 마이크로 태스크 큐와 렌더링 과정
  • safari invalid date error
  • 자바스크립트 모듈 시스템
  • 자바스크립트 채팅방 스크롤

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
jiho_bae

Go devlog

JavaScript/theory

[자바스크립트] 일반 객체 다루기

2022. 1. 11. 16:36

이전 글

 

[객체] 자바스크립트에서 객체를 생성하는 다양한 방법

객체 객체란, key:value 쌍을 저장하는 자료구조로, 하나의 변수에 여러 속성들을 저장할 수 있도록 돕는다. 사실, 자바스크립트의 거의 모든 것들은 객체라고 할 수 있다. 배열, 함수, 객체, 날짜,

gobae.tistory.com

 

객체 자체를 먼저 다뤘어야 했는데, 어쩌다보니 순서가 좀 뒤바뀌게 되었다.

이번 포스팅에서는 자바스크립트에서의 일반 객체(순수 객체)에 대해 정리한다.


객체

자바스크립트에서 객체는 중괄호 {} 를 이용해 만들 수 있다.

 

각 원소들은 각각 key:value 쌍으로 구성된다.
key는 문자형이어야만 하고 value로는 모든 자료형이 허용된다.

 

객체의 원소는 프로퍼티(property)라고 하며,
key는 이름으로 value를 찾기 위한 라벨이라고 볼 수 있다.

 

객체를 생성하는 대표적인 두가지 방법을 소개하면,

    const obj = new Object(); // 객체 생성자
    const obj = {}; // 객체 리터럴

이 두가지가 있다.

 

new 키워드를 이용하는 생성자 방법과 중괄호를 이용해 선언하는 리터럴 방법이다.


객체 프로퍼티의 생성, 불러오기, 추가, 삭제

생성하기

    const player = {
      name : 'Tom',
      age : 12,
      level : 7,
      'soul food' : 'banana',
      'created_at' : '20220111',
    };

player 객체가 존재한다고 할 때, 아래와 같이 해석한다.

 

객체 player는 객체 리터럴로 선언되었다.
5개의 프로퍼티가 있고, 키 값으로 name, age, level, soul food, created_at이 있으며 그에 해당하는 값들이 존재한다.


불러오기

객체를 불러오는 다양한 방법이 있다.

    console.log(player.name); // O
    console.log(player['name']); // O

    console.log(player.created_at); // O
    console.log(player['created_at']); // O

    console.log(player['soul food']); // O

    console.log(player[name]); // X
    console.log(player.soul food) // X

가능한 방법과 가능하지 않은 방법을 표시해뒀다.

 

점 표기법(dot notation)을 이용하거나, 대괄호 표기법 []을 이용해 값을 조회할 수 있다.

점 표기법을 이용할 때는 key가 유효한 변수 식별자여야 한다.

 

※ 유효한 변수 식별자란?

공백이 없어야 하며, 숫자로 시작하지 않아야 하고 $ _ 를 제외한 특수 문자를 포함할 수 없다.

 

그래서 soul food와 같이 여러 단어가 조합된 키는 대괄호 표기법 []을 이용해야 한다.

대괄호 표기법 [] 안에는 점 표기법과 동일하게 키 이름을 적어주는데, 반드시 문자열로 적어줘야 한다.
문자열이 아닌 변수를 넣어주면, 런타임 시에 변수가 평가되어 변수에 할당된 값을 키 이름으로 취급하여 조회하게 된다.

 

이건 코드를 통하면 쉽게 이해가 될 듯 하다.

    const obj = {
      name : 'Tom',
      Tom : 'its not name',
    };

    const name = 'Tom';

    console.log(obj.name) // 'Tom'
    console.log(obj['name']) // 'Tom'
    console.log(obj[name]) // 'its not name' (런타임 시 name 변수값을 이용해서 obj['Tom'] 으로 평가된다.)

추가하기

    const obj = {
      name : 'Tom'
    };

    obj.age = 17;
    obj['food'] = 'banana'; 

    obj[hobby] = 'tennis'; // X

객체에 프로퍼티를 추가하는 것도 마찬가지다.


엄밀히 말하면, 기존에 해당 키 이름이 존재하면 값의 변경이 되며, 키 이름이 존재하지 않으면 생성(추가)가 된다.

 

마지막에 적힌 obj[hobby]는 오류가 발생하는데, hobby 변수가 존재하지 않기 때문이다.

키 이름이 hobby인 프로퍼티를 생성하고 싶다면, obj['hobby'] 로 작성해야 한다.


삭제하기

    const obj = {
      name : 'Tom',
      age : 17
    };

    delete obj.name;
    console.log(obj); // {age : 17}

delete 키워드를 이용하면, 객체에서 프로퍼티를 삭제할 수 있다.


대괄호 표기법 응용하기

대괄호 표기법 []은 생각보다 더 강력하다.

 

런타임 시 사용자로부터 입력받은 값 등을 변수를 이용하면 변수의 값에 해당하는 키 이름을 설정할 수 있다.

    const name = 'Tom';
    const userObj = {};
    userObj[name] = 1;

    console.log(userObj) // {Tom : 1}

변수 name 값이 런타임 시 평가되어 userObj[name]이 userObj['Tom'] 으로 평가되어 key:value로 'Tom' : 1 을 생성한다.

 

이렇게 변수가 평가된 값을 이용한 프로퍼티 생성이 이루어짐을 응용하면,

    const nameList = ['Tom','Juliet','Jack','Whale'];
    const nameObj = {};

    nameList.forEach(name => nameObj[name] = 1);
    console.log(nameObj); // {Tom: 1, Juliet: 1, Jack: 1, Whale: 1}

다음과 같이 각 리스트의 원소들을 key 이름으로 가지도록 할 수도 있다.

 

 

점 표기법을 이용해서 이 예시와 같은 객체를 만드는 작업은 아래와 같은데

    const nameObj = {};
    name.Tom = 1;
    name.Juliet = 1;
    name.Jack = 1;
    name.Whale = 1;
    console.log(nameObj); // {Tom: 1, Juliet: 1, Jack: 1, Whale: 1}

다행히 원소가 4개라서 망정이지, 10개만 넘어가도 답이 없음은 분명하다.


계산된 프로퍼티

객체 리터럴 {} 로 객체를 생성할 때, 프로퍼티의 키 이름을 대괄호로 둘러 쌀 수 있다.


이를 계산된 프로퍼티(Computed Property) 라고 한다.

    const hobby = prompt('좋아하는 운동은?');
    const favorite = {
      [hobby] : true
    };
    console.log(favorite); // { tennis : true }

대충 사용자가 브라우저에서 prompt에 좋아하는 운동으로 tennis을 입력했다고 하면, 결과는 위와 같다.

 

물론, 위 코드는 아래 코드와 동일하게 동작한다.

    const hobby = prompt('좋아하는 운동은?');
    const favorite = {};
    favorite[hobby] = true;

    console.log(favorite); // { tennis : true }

 

 

추가로 변수 값을 이용해서 프로퍼티를 생성할 때,
기존 변수값에 추가하고 싶은 문자열 등을 추가해서 키 이름으로 생성할 수도 있다.

    const name = 'Tom';
    const comic = {
        [name + 'AndJerry'] : 'NO!',
    };
    console.log(comic); // { TomAndJerry : 'No!' }


    // 혹은 이렇게도 가능

    const nameList = ['Tom', 'Jane', 'Kane'];
    const team = {};

    nameList.forEach(name => {
      team[name + 'hobby'] = 'soccer';
      team[name + 'year'] = 22;
    });
    console.log(team); // {Tomhobby: 'soccer', Tomyear: 22, Janehobby: 'soccer', Janeyear: 22, Kanehobby: 'soccer', …}

이와 같이 [변수 + '추가하고자 하는 문자열'] 의 조합이 가능하다.
런타임 시 변수가 문자열로 평가되므로, ['문자열' + '문자열'] = ['이어 붙인 문자열'] 이 되는 원리이다.


키, 값이 중복될 시 단축이 가능

기존 변수 값들을 프로퍼티로 삼아 객체를 새로 생성해야 하는 상황이 있다.

    const name = 'Tom';
    const age = 17;

    const user = {
        name:name,
          age:age
    };

    // 이와 같이 key:value의 값이 겹친다면 단축이 가능하다.

    const shortUser = {
      name,
      age
    };

name:name 과 단축된 name은 같은 역할을 한다.
name:name 에서 콜론(:)의 왼쪽 name은 키 이름에 해당하며 우측 name은 변수값에 해당한다.


즉 현재 변수 name 값이 'Tom' 이므로 name:'Tom' 이 생성되며,
단축된 name으로 프로퍼티를 선언해도 위와 동일하게 생각하면 된다.

 

이렇게 단축 프로퍼티를 사용하면?

    const obj = {
      name:name,
      age:age,
      hobby:hobby
    };

    // 위의 코드를

    const obj = {name, age, hobby};
    // 이렇게 획기적으로 줄일 수 있다. 👍

키 이름으로 숫자 사용하기

키 이름으로 숫자를 사용할 수도 있다.

 

여기서는 위에서 설명했던 방법과 조금 다를 수 있겠다.

    const obj = {
      0: 'Tom',
      1: 'Jane',
      2: 'Kane',
    };

    console.log(obj['0']); // O
    console.log(obj[0]); // O
    console.log(obj.0); // X

obj['0'] 의 경우, '0'의 키 이름을 조회하므로 정상 동작한다.

 

obj[0]의 경우, 숫자 0은 변수가 될 수 없으므로 문자열로 자동 형변환이 된다.
그러므로 obj[0] = obj['0'] 취급되어 위와 동일하게 정상 동작한다.

 

obj.0의 경우, 앞서 언급한 유효한 변수 식별자에 어긋난다.

dot notation(.) 바로 뒤에 숫자로 시작할 수 없다.


객체에 특정 프로퍼티가 존재하는지 확인하기

객체에 특정한 프로퍼티 키 이름이 존재하는지 확인해야 하는 상황이 종종 있다.

 

필자는 그럴 때 마다 프로퍼티가 존재하지 않는 것을 검출하기 위해서
if(!obj.name) blahblah 와 같은 방식을 사용했으나
in 연산자로 존재 여부 확인이 가능하다.

 

    const obj = {
      name : 'Tom',
      age : 17
    };

    console.log(!obj.name) // false;
    console.log(!obj.hobby) // true;

    console.log('name' in obj); // true
    console.log('hobby' in obj); // false

 

사실 !obj.hobby === !undefined === true 이기 때문에, 현재는 기능적으로 문제는 없는 것 처럼 보이지만

 

    const obj = {
      name : 'Tom',
      age : 17,
      hobby : undefined
    };

    console.log(!obj.hobby); // true
    console.log('hobby' in obj) // true

이렇게 hobby 키를 가진 프로퍼티가 존재할 수도 있기 때문에, 완벽한 검증이 아닐 수 있다.

 

또한 여기서도 문자열 in 객체 형식으로 'hobby' in obj 형태를 이용해야 한다.
hobby in obj를 타이핑해서 엉뚱한 hobby 변수 값을 조사해서 에러를 일으키지 말자.


객체 순회하기

객체도 배열처럼 순회할 수 있다.

 

for in 문법을 이용하면 된다.

    const obj = {
      name : 'Tom',
      age : 17,
      hobby : 'tennis'
    };

    for(let key in obj){
      console.log(key, obj[key]);
    };

    // name Tom
    // age 17
    // hobby tennis

다음과 같이 in 키워드로 키를 조회하며, 객체[키]로 값을 함께 조회할 수 있다.

 

 

필자는 Object의 메서드를 이용한 조회를 더 많이 사용한다.

 

Object.keys - 모든 키를 포함한 1차원 배열 반환
Objecy.values - 모든 값을 포함한 1차원 배열 반환
Object.entries - [키, 값] 쌍의 2차원 배열 반환

    const obj = {
      name : 'Tom',
      age : 17,
      hobby : 'tennis'
    };

    console.log(Object.keys(obj)); // ['name', 'age', 'hobby']
    console.log(Object.values(obj)); // ['Tom', 17, 'tennis']

    console.log(Object.entries(obj));
    /*
    [
        ['name', 'Tom'],
        ['age', 17],
        ['hobby', 'tennis']
    ]
    */

객체 사용시 유의점

객체와 같은 참조값을 사용할 시 유의할 점이 있다.

    const name = 'Tom';
    const obj = {
      name:'Tom'
    };

    name = 'Jane' // X

    obj = {
      name : 'Jane
    }; // X

    obj.name = 'Jane' // O

const 키워드로 선언한 변수는 재할당이 불가능하다.

즉 새로운 값으로 바꿀 수 없다.

 

위와 같이 name, obj 변수에 재할당이 불가능하지만, obj의 프로퍼티에 대한 변경은 가능하다.

 

obj 변수에는 '객체 자체'가 할당된 것이 아니라, '객체의 주소값' 이 할당되어 있어서
const 키워드는 '주소값'을 기억하고 있기 때문에 '주소값'을 변하게 하는 재할당이 불가능하지만, 객체의 프로퍼티를 변경이 될 수 있다.

 

즉, obj 객체의 껍질 자체는 불변이지만 obj 객체의 내부 프로퍼티들은 불변이 아니라고 이해하면 되겠다.

 

 

또한 이와 같이 obj 변수가 '주소값' 임을 이해하게 되면, 한가지 의문점을 더 해결할 수 있는데

    const user = {
        name:'Tom',
          phone:01000000000
    };

    function takeANumber(customer){
      customer.number = 0;
      console.log(customer);
    }

    takeANumber(user); // {name: 'Tom', phone: 134217728, number: 0}

    console.log(user); // {name: 'Tom', phone: 134217728, number: 0}

위와 같이 함수 매개변수로,
user를 넣어줬을 때 '복사' 되었다고 착각할 수 있는데
매개변수로 넣어준 user 객체에 name 프로퍼티가 생성되는 상황이 왜 발생하는지 이해하게 된다.

 

takeANumber에서 customer 매개변수가 user의 주소 값을 가지고 있다.
그래서 주소값에 있는 객체에 number:0의 프로퍼티를 생성한 것일 뿐이다.

 

 

만약 기존 객체를 변경하지 않으면서 takeANumber 함수를 이용하고 싶다면,
다양한 방법이 있겠지만 가장 간단한 방법으로는 spread operator를 사용하길 권장한다.

    const user = {
        name:'Tom',
          phone:01000000000
    };

    function takeANumber(customer){
      customer.number = 0;
      console.log(customer);
    }

    takeANumber({...user}); // {name: 'Tom', phone: 134217728, number: 0}

    console.log(user); // {name: 'Tom', phone: 134217728}

spread operator는 '전개구문' 이라 부르며,

이름 그대로 해당 객체 / 배열 등을 풀어준다고 생각하면 된다.

 

물론 이 방법이 완전한 것은 아니다.


'얕은 복사'를 수행하기 때문에, 객체 혹은 배열 내에 값으로 또 다른 배열이나 객체를 포함한다면 다른 방법을 사용해야 한다.


출처

https://ko.javascript.info/object

https://doitnow-man.tistory.com/130

저작자표시 (새창열림)

'JavaScript > theory' 카테고리의 다른 글

래퍼 객체(Wrapper Object)란?  (0) 2022.01.14
[자바스크립트] V8 엔진의 메모리 관리 이해하기  (0) 2022.01.12
[자바스크립트] 고차함수와 배열 내장 메서드  (0) 2022.01.06
[함수형] 클로저 Closure에 대해 알아보자.  (0) 2022.01.06
[객체] 자바스크립트에서 객체를 생성하는 다양한 방법  (0) 2022.01.04
    'JavaScript/theory' 카테고리의 다른 글
    • 래퍼 객체(Wrapper Object)란?
    • [자바스크립트] V8 엔진의 메모리 관리 이해하기
    • [자바스크립트] 고차함수와 배열 내장 메서드
    • [함수형] 클로저 Closure에 대해 알아보자.
    jiho_bae
    jiho_bae
    하루에 한 걸음씩

    티스토리툴바