상세 컨텐츠

본문 제목

[Codecademy] Learn JavaScript 8. Objects

21-22/21-22 리액트 스타터 -2

by dev otcroz 2021. 10. 11. 14:02

본문

728x90

8. Objects

● Objects

1. Introduction to Objects 객체를 들어가며

 자바에는 7개의 데이터 타입이 있다.

- string, number, boolean, null, undefined, symbol, objects

-자바스크립트(Javascript)의 기본 타입은 객체(Object)

객체를 사용하면 실제 사물을 모델링하거나 데이터 구조를 구축할 수 있다.

사과(apple), 테이블(table), 아기(baby), 지렁이(worm)을 객체로 만들 수 있다.

 

*객체: 속성값과 행동을 가진 데이터 타입

*객체 모델링: 객체의 속성과 동작을 추려내어 객체로 구현하는 과정

 


2. Creating Object Literals 객체 리터럴 만들기

객체를 선언할 때 기본구조

- 객체를 변수에 할당하는 구조

중괄호({})를 사용하여 객체 리터럴을 선언한다.

- 객체를 수정할 수 있도록 let 예약어를 사용하였다. const를 사용하여 객체를 선언할 수 있다. 

let spaceship = {}; // 비어있는 객체 생성

객체는 여러 개의 키-값 쌍으로 이루어져 있다. 이때, 키-값 쌍을 콤마(,)로 구분해준다. 

키-값 쌍의 집합을 프로퍼티(Property)라고 한다. 

  • 객체(object): 중괄호를 사용하여 객체를 선언, 중괄호 안에 키-값 쌍을 선언한다.
  • 키(key): 값(value)이 저장되어 있는 메모리의 위치를 가리킨다. 변수 이름 또는 식별자가 작성되는 위치
  • 값(value): 데이터의 정보가 들어가는 공간이다.

 

Instruction

1.  프로퍼티(키-값 쌍)가 있는 객체 생성하기

let fasterShip ={
  color : 'silver',
  'Fuel Type': 'Turbo Fuel'
};

let 예약어로 사용하여 fasterShip라는 객체를 만들었다.

  • 키(key): 'Fuel Type', color
  • 값(value): 'Turbo Fuel', 'silver'

 

fasterShip은 color가 silver,

'Fuel Type'이 'Turbo Fuel'인 객체이다.

 


3. Accessing Properties 프로퍼티에 접근하기

프로퍼티에 접근할 수 있는 방법

  1. 도트 연산자(.) 사용하기
  2. 대괄호 연산자([ ]) 사용하기
'hello'.length; //return 5

.length는 길이를 출력한다. 즉, hello.length는 5를 출력한다.

 

첫 번째 방법인 도트 연산자(.)를 사용하면 객체의 프로퍼티와 메서드에 접근할 수 있다.

let spaceship = {
  homePlanet: 'Earth',
  color: 'silver'
};
spaceship.homePlanet; // Returns 'Earth',
spaceship.color; // Returns 'silver',
spaceship.going // Returns undefined
  • spaceship 객체의 프로퍼티 값에 접근하기 위해 도트 연산자(.)를 사용한다.
  • 객체 이름.프로퍼티 이름(키); 의 형태로 프로퍼티 값에 접근할 수 있다.
  • 존재하지 않는 프로퍼티 이름에 접근하려고 하면 undefined를 리턴한다.

 

Instruction

1.  도트 연산자(.)를 사용하여 객체의 프로퍼티 값에 접근하기

let spaceship = {
  homePlanet: 'Earth',
  color: 'silver',
  'Fuel Type': 'Turbo Fuel',
  numCrew: 5,
  flightPath: ['Venus', 'Mars', 'Saturn'],
  
};

let crewCount = spaceship.numCrew;
let planetArray = spaceship.flightPath;
  1. 객체 spaceship를 만든다. 이때 프로퍼티 이름은 homePlanet, color, 'Fuel Type', numCrew, flightPath를 가진다.
  2. 각각의 프로퍼티에 값을 할당하였다. ('Earth', 'silver', 'Turbo Fuel', 5, ['Venus', 'Mars', 'Saturn'])
  3. spaceship.numCrew : 도트 연산자(.)를 사용하여 객체 이름 spaceship를 통해 프로퍼티 numCrew에 접근하였다. 이때 접근한 값은 crewCount 변수에 저장된다.
  4. spaceship.flightPath : 도트 연산자(.)를 사용하여 객체 이름 spaceship를 통해 프로퍼티 flightPath에 접근하였다. 이때 접근한 값은 planetArray 변수에 저장된다.

4. Bracket Notation 대괄호 연산자

프로퍼티에 접근할 수 있는 또 다른 방법으로 대괄호 연산자([ ])를 사용한다.

객체 ['프로퍼티 이름(키)'];

let spaceship = {
  'Fuel Type': 'Turbo Fuel',
  'Active Duty': true,
  homePlanet: 'Earth',
  numCrew: 5
};
spaceship['Active Duty'];   // Returns true
spaceship['Fuel Type'];   // Returns 'Turbo Fuel'
spaceship['numCrew'];   // Returns 5
spaceship['wooo'];   // Returns undefined

 

  1. let spaceship: 4개의 프로퍼티를 가지는 spaceship 객체를 선언하였다.
  2. spaceship[ ]: 객체 이름에 각각 대괄호 연산자 [ ]를 통해 프로퍼티 값에 접근하였다.
  3. spaceship['wooo']: wooo라는 프로퍼티 이름(key)이 존재하지 않기 때문에 undefind를 반환한다.

 

화살표 함수를 사용하여 해당하는 객체의 프로퍼티 값을 리턴하는 방법이 있다.

let returnAnyProp = (objectName, propName) => objectName[propName];
 
returnAnyProp(spaceship, 'homePlanet');
  1. returnAnyProp에서 objectName, propName을 사용하여 objectName[propName]; 형태의 함수를 만들었다.
  2. returnAnyProp 함수를 호출하여 값을 반환받는다. 예시에서는 함수롤 호출하면 함수 내에서 spaceship['homePlanet'] 형태로 동작하여 프로퍼티의 값을 얻을 수 있다.

 

Instruction

1.  대괄호 연산자([ ])를 사용하여 객체의 프로퍼티 값에 접근하기

let spaceship = {
  'Fuel Type' : 'Turbo Fuel',
  'Active Mission' : true,
  homePlanet : 'Earth', 
  numCrew: 5
 };

let propName =  'Active Mission';

let isActive = spaceship[propName];
console.log(isActive)  // Output: true
  1. 4개의 프로퍼티('Fuel Type', 'Active Mission', homePlanet, numCrew)를 갖는 객체 spaceship를 선언하였다. 
  2. let propName을 선언하여 'Active Mission'을 변수에 할당한다.
  3. let isActive를 선언하여 spaceship[propName]을 변수에 할당한다. 이때, 대괄호 연산자([ ])를 통하여 프로퍼티 값에 접근할 수 있다.
  4. console.log()를 통해 값(true)을 출력한다. 

5. Property Assignment 프로퍼티 할당

객체를 선언할 때, 각 프로퍼티 값에 값을 할당한 후, 나중에 프로퍼티에 값을 재할당할 수 있다.

대괄호 연산자([ ]), 도트 연산자(.), 할당 연산자(=)를 사용하여 값을 할당한다.

  • 객체 이름 spaceship을 쓰고 대괄호 연산자([ ]) 안에 '프로퍼티 이름'을 작성
  • 객체 이름 spaceship을 쓰고 도트 연산자(.), 프로퍼티 이름을 작성

그리고 등호 연산자(=)를 사용하여 프로퍼티에 값을 할당한다.

 

const spaceship = {type: 'shuttle'};
spaceship = {type: 'alien'}; // TypeError
spaceship.type = 'alien'; 
spaceship.speed = 'Mach 5';
  1. 1행: { type: 'shuttle' }을 프로퍼티로 갖는 객체를 생성한다.
  2. 2행: const로 선언된 객체를 재할당하려고 하면 오류가 발생한다.
  3. 3행: spaceship 객체에 type 프로퍼티의 값을 'alien'으로 변경한다.
  4. 4행: speed 프로퍼티를 객체에 추가하고 'Mach 5'값을 할당한다.

객체(spaceship)에 호출한 프로퍼티(speed)가 존재하지 않을 때, 프로퍼티를 객체에 추가하고 값('Mach 5')을 할당한다.

이 객체는 const로 선언되어 객체 자체의 재할당을 불가능하지만, 객체 내에 있는 프로퍼티는 재할당이 가능하다.

 

객체의 프로퍼티를 삭제할 때 delete 객체이름.프로퍼티를 써준다.

const spaceship = {
  'Fuel Type': 'Turbo Fuel',
  homePlanet: 'Earth',
  mission: 'Explore the universe' 
};
 
delete spaceship.mission;  // mission 프로퍼티 삭제

마지막 행에 delete spaceship.mission를 써주어 mission 프로퍼티를 삭제했다.

 

Instruction

1.  객체 내의 프로퍼티에 값을 할당하기

let spaceship = {
  'Fuel Type' : 'Turbo Fuel',
  homePlanet : 'Earth',
  color: 'silver',
  'Secret Mission' : 'Discover life outside of Earth.'
};

spaceship.color = 'glorious gold';
spaceship['numEngines'] = 9;

delete spaceship['Secret Mission']
  1. let spaceship ={} : 4개의 프로퍼티를 가진 객체를 선언한다.
  2. spaceship.color로 도트 연산자(.)를 통해 프로퍼티의 값에 접근, color 프로퍼티의 값을 'glorious gold'로 변경한다.
  3. spaceship['numEngines']로 대괄호 연산자([ ])를 통해 프로퍼티의 값에 접근, numEngines 프로퍼티의 값을 9로 변경한다.
  4. spaceship에 있는 'Secret Property' 프로퍼티가 삭제된다.

6. Methods 메서드

객체에 저장되어 있는 함수를 메서드라고 한다.

프로퍼티는 객체의 속성이라고 보았을 때, 메서드는 객체의 행동을 정의한다.

 

우리는 메서드의 예를 이미 많이 본 적이 있다. console.log()에서 log()는 console 객체의 메서드이다.

또, math.floor()에서 floor()은 math 객체의 메서드이다.

 

메서드를 선언하는 방법

  • function() 익명함수 사용
  • 함수 이름() : ES6 이후에 function 키워드와 콜론(:)을 사용하지 않는 방법
const alienShip1 = {
  invade: function () { 
    console.log('Hello! We have come to dominate your planet. Instead of Earth, it shall be called New Xaculon.')
  }
};

const alienShip2 = {
  invade () { 
    console.log('Hello! We have come to dominate your planet. Instead of Earth, it shall be called New Xaculon.')
  }
};
  1. alienship1는 익명함수를 사용하여 메서드를 선언한다.
  2. alienship2는 함수이름( ) 형식을 사용하여 메서드를 선언한다. 

 

Instruction

1.  객체 내에서 메서드 생성과 호출하기

let retreatMessage = 'We no longer wish to conquer your planet. It is full of dogs, 
which we do not care for.';

// Write your code below

let alienShip = {
  retreat() {
    console.log(retreatMessage);
  },
  takeOff(){
    console.log('Spim... Borp... Glix... Blastoff!');
  }
}

alienShip.retreat(); // retreat()내에 있는 내용 동작 
alienShip.takeOff(); // takeOff()내에 있는 내용 동작
  1. let retreatMessage : let 예약어로 변수를 선언 후 동시에 값을 할당한다.
  2. let으로 선언한 alianShip에 retreat() takeoff() 메서드를 선언하고 중괄호({})내에 동작을 정의했다.
  3. alianship.메서드()를 통해 객체 내에 메서드를 호출하였고, 각 함수가 동작을 수행하였다.

7. Nested Objects  중첩 객체

객체 내에서 또 다른 객체를 선언하는 것을 중첩 객체라고 한다.

const spaceship = {
     telescope: {
        yearBuilt: 2018,
        model: '91031-XLT',
        focalLength: 2032 
     },
    crew: {
        captain: { 
            name: 'Sandra', 
            degree: 'Computer Engineering', 
            encourageTeam() { console.log('We got this!') } 
         }
    },
    engine: {
        model: 'Nimbus2000'
     },
     nanoelectronics: {
         computer: {
            terabytes: 100,
            monitors: 'HD'
         },
        'back-up': {
           battery: 'Lithium',
           terabytes: 50
         }
    }
};

spaceship 객체 안에 telescope, crew, engine, nanoelectronics 4개의 객체가 생성되었다.

또 crew 객체 밑에 captain 객체를 선언하고, nanoelectronics 객체 밑에 computer, 'back-up' 객체가 생성되었다.

 

중첩된 객체의 프로퍼티에 접근하는 방법은 도트 연산자(.)와 대괄호 연산자([ ])를 사용한다.

spaceship.(프로퍼티 이름)

//객체 1번 중첩
spaceship.telescope.model;  // Returns '91031-XLT'

//객체 2번 중첩
spaceship.nanoelectronics['back-up'].battery; // Returns 'Lithium'
spaceship.crew.captain.name; //return sandra

 

Instruction

1.  중첩 객체를 생성하고 중첩 객체 내에 있는 프로퍼티 값 리턴하기

let spaceship = {
  telescope: {
    yearBuilt: 2018,
    model: "91031-XLT",
    focalLength: 2032 
  },
  crew: {
    captain: { 
      name: 'Sandra', 
      degree: 'Computer Engineering', 
      encourageTeam() { console.log('We got this!') },
     'favorite foods': ['cookies', 'cakes', 'candy', 'spinach'] }
  },
}; 

let capFave = spaceship.crew.captain['favorite foods'][0]; // Returns cookies
let firstPassenger = spaceship.telescope.yearBuilt; // Returns 2018
  1. spaceship 객체 내에 telescope 객체와 crew 객체가 선언되어 있다. 또, crew 객체에 captain 객체가 선언되어 있다.
  2. let capfave가 선언된 행에서 도트 연산자(.)와 대괄호 연산자([ ])를 사용하여 captain 객체에 있는 'favorite foods'에 접근하였고 'favorite foods' [0]의 값인 cookies가 반환된다. 반환된 cookies를 capfave 변수에 저장한다.
  3. 도트 연산자(.)를 통하여 telescope 객체 내의 프로퍼티인 yearBuilt 값에 접근한다. 즉, 2018을 반환하고 firstPassenger 변수에 저장한다.

 


8.  참조에 의한 전달

객체는 참조를 통해 값에 접근하고 변경할 수 있다.

객체에 할당된 프로퍼티를 함수의 인수로 전달하면  함수는 인수를 매개변수로 받게 되고, 그 매개변수는 객체의 프로퍼티를 가리키는 상태가 된다. 즉, 함수를 통해 객체의 프로퍼티를 참조(접근, 변경)할 수 있다.

const로 선언한 객체의 경우에도 함수를 통해 객체의 프로퍼티를 참조할 수 있다.

const spaceship = {
  homePlanet : 'Earth',
  color : 'silver'
};
 
let paintIt = obj => {
  obj.color = 'glorious gold'
};
 
paintIt(spaceship);
 
spaceship.color // Returns 'glorious gold'
  1. const spaceship : const 예약어로 객체 spaceship을 선언하였으며, homePlanet, color 프로퍼티 2개가 객체 내에 선언되었다.
  2. let paintIt : 화살표 함수 구현, obj를 매개변수로 받아서 color 프로퍼티에 접근할 수 있도록 obj.color을 구현하였다.
  3. paintIt(spaceship) : paintIt 함수를 호출하였다. spaceship(객체)를 인수로 전달하고, 함수 내에서 spaceship.color의 값을 참조하여 'glorious gold'로 변경하였다.
  4. spaceship.color : spaceship 객체의 color 프로퍼티의 값을 출력한다.

 

Instruction

1.  함수를 통해 객체의 프로퍼티 참조하기

let spaceship = {
  'Fuel Type' : 'Turbo Fuel',
  homePlanet : 'Earth'
};

let greenEnergy = obj => {
  obj['Fuel Type'] = 'avocado oil';
}

let remotelyDisable = obj => {
  obj.disabled = true;
}

greenEnergy(spaceship);
remotelyDisable(spaceship);
  1. spaceship 객체를 선언하였고, 객체 내의 2개의 프로퍼티('Fuel Type', homePlanet)를 선언하였다.
  2. let greenEnergy 함수: 매개변수 obj를 통해 'Fuel Type' 프로퍼티를 참조할 수 있도록 구성하였다.
  3. let remotelyDisable 함수: 매개변수 obj를 통해 disabled에 프로퍼티를 참조할 수 있도록 구성하였다.
  4. greenEnergy(spaceship) : 객체 spaceship를 인수로 넣어 객체에 있는 'Fuel Type' 프로퍼티의 값을 'avocado oil'로 변경하였다.
  5. remotelyDisable(spaceship) : 객체 spaceship를 인수로 넣어 객체에 있는 disabled 프로퍼티의 값을 true로 변경하였다. 

9. 객체를 통한 반복

반복문은 조건이 충족될 때까지 코드를 반복하는 구조이다. 

객체 내의 프로퍼티 또는 객체의 내용을 반복문 for ... in을 통하여 중첩 객체의 프로퍼티를 참조하여 출력할 수 있다.

객체 내의 프로퍼티의 값을 출력할 때 ${ }(문자열 지간)을 활용하여 출력할 수 있다.

 

for ... in에 관한 내용 자세히 보기 

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...in

 

let spaceship = {
  crew: {
    captain: { 
      name: 'Lily', 
      degree: 'Computer Engineering', 
      cheerTeam() { console.log('You got this!') } 
    },
    'chief officer': { 
      name: 'Dan', 
      degree: 'Aerospace Engineering', 
      agree() { console.log('I agree, captain!') } 
    },
    medic: { 
      name: 'Clementine', 
      degree: 'Physics', 
      announce() { console.log(`Jets on!`) } },
    translator: {
      name: 'Shauna', 
      degree: 'Conservation Science', 
      powerFuel() { console.log('The tank is full!') } 
    }
  }
}; 
 
for (let crewMember in spaceship.crew) {
  console.log(`${crewMember}: ${spaceship.crew[crewMember].name}`);
}
  1. spaceship 객체가 선언했고, spaceship 객체 내에 crew 객체, 또 객체 내에 또 다른 객체(captain, 'chief officer', medic, translator)를 선언했다. (중첩 객체) spaceship > crew > captain, 'chief officer', medic, translator
  2. for in 구문: spaceship.crew에 해당하는 것을 crewMember가 받는다. 후에  `${crewMember}`(문자열 지간)을 사용하여 반복적으로 값을 출력한다. 
  3. ${crewMember} : spaceship.crew에 해당하는 프로퍼티들을 출력한다.
  4. ${spaceship.crew[crewMember].name} : spaceship.crew에 있는 각 객체에서 name 프로퍼티의 값을 반복문으로 출력한다.

Print )

Captain : 'Lily'

'Chief Officer' : 'Dan' 

medic : 'Clementine'

translator : 'Shauna'

 

Instruction

1.  for ... in 반복문을 사용하여 객체 프로퍼티 반복 출력하기

let spaceship = {
    crew: {
    captain: { 
        name: 'Lily', 
        degree: 'Computer Engineering', 
        cheerTeam() { console.log('You got this!') } 
        },
    'chief officer': { 
        name: 'Dan', 
        degree: 'Aerospace Engineering', 
        agree() { console.log('I agree, captain!') } 
        },
    medic: { 
        name: 'Clementine', 
        degree: 'Physics', 
        announce() { console.log(`Jets on!`) } },
    translator: {
        name: 'Shauna', 
        degree: 'Conservation Science', 
        powerFuel() { console.log('The tank is full!') } 
        }
    }
}; 

for (let crewmember in spaceship.crew){
  console.log(`${spaceship.crew[crewmember].name} : ${spaceship.crew[crewmember].degree}`);
};
  1. 객체를 선언하였다. spaceship > crew > captain, 'chief officer', medic, translator
  2. for ... in 구문에서 spaceship.crew에 해당하는 것을 crewMember가 받는다. 후에 `${}`사용하여 반복적으로 값을 출력한다. 
  3. `${spaceship.crew[crewmember].name} : spaceship에서 crew 객체 내에서 crewMember에 해당하는 것의 name 프로퍼티를 출력한다.
  4. '${spaceship.crew[crewmember].degree}` : spaceship에서 crew 객체 내에서 crewMember에 해당하는 것의 degree 프로퍼티를 출력한다.

Print)

Lily : Computer Engineering

Dan : Aerospace Engineering

Clementine : Physics

Shauna : Conservation Science

 


● Advanced Objects

1. Advanced Objects Introduction

 앞서 살펴본 바로, 자바스크립트의 객체는 데이터의 기능을 저장하는 컨테이너이다.

이후 다룰 컨텐츠에서는 객체 생성의 기본 원리를 바탕으로 몇 가지 고급 개념을 살펴본다.

  • this 명령어 사용하기
  • 정보 은닉 방법 알아보기
  • getter 메소드와 setter 메소드 정의하기
  • 팩토리 함수 만들기
  • 구조 분해 할당 알아보기

2. The this KeyWord : this 명령어

 객체의 메소드로 객체가 갖고 있는 프로퍼티를 출력하려면 어떻게 해야 할까?

아래와 같은 접근은 ReferenceError를 불러일으킨다.

const goat = {
  dietType: 'herbivore',
  makeSound() {
    console.log('baaa');
  },
  diet() {
    console.log(dietType);
  }
};
goat.diet(); 
// Output will be "ReferenceError: dietType is not defined"

이때 this를 참조하도록 하면 의도한 대로 동작하는 것을 확인할 수 있다. this 명령어는 호출하는 객체를 참조한다.

const goat = {
  dietType: 'herbivore',
  makeSound() {
    console.log('baaa');
  },
  diet() {
    console.log(this.dietType);
  }
};
 
goat.diet(); 
// Output: herbivore

위의 예에서 this가 가리키는 것은 goat로, goat의 dietType 프로퍼티를 호출한다.

 

Instruction

1. 새 객체 robot을 생성한다. 이 객체는 model 프로퍼티에 '1E78V2', energyLevel 프로퍼티에 100의 값을 갖고 있다.

2. provideInfo() 메소드를 생성하고, 문자열 I am MODEL and my current energy level is ENERGYLEVEL.  을 리턴하도록 한다. MODEL, ENERGYLEVEL을 각각 model, energyLevel 프로퍼티로 대체한다. this 키워드를 사용해야 한다.

3. provideinfo()를 호출해 콘솔에 출력한다.

const robot = {
  model : '1E78V2',
  energyLevel : 100,
  provideInfo(){
    return `I am ${this.model} and my current energy level is ${this.energyLevel}.`
  }
};

console.log(robot.provideInfo());

3. Arrow Functions and this : 화살표 함수와 this

 앞서 객체가 자신의 프로퍼티에 접근하려면 this 명령어를 이용한다는 것을 살펴보았다. 이를 화살표 함수에 적용하면 조금 더 복잡한 구조를 갖는다.

const goat = {
  dietType: 'herbivore',
  makeSound() {
    console.log('baaa');
  },
  diet: () => {
    console.log(this.dietType);
  }
};
 
goat.diet(); // Prints undefined

 화살표 함수는 기본적으로, 내부의 코드를 호출한 개체가 아닌 함수 자체에 바인딩하거나 연결한다. 위의 코드에서 this의 값은 goat를 참조하는 것이 아닌 전역 객체 또는 전역 범위에 존재하는 객체이며, 이는 dietType 속성을 갖고있지 않다. 따라서 undefined가 출력된 것이다. 이러한 논리적 오류를 범하지 않으려면 화살표 함수 내 this 키워드의 사용을 피해야 한다.

 

 전역 변수와 화살표 함수에 대해 자세히 알아보려면 아래 문서를 확인하라.

- Global object

https://developer.mozilla.org/en-US/docs/Glossary/Global_object

- Arrow function expressions

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions

 

Instruction

1. 화살표 함수를 재구성하라. (화살표 함수를 일반 함수의 형태로 변경하였다.)

const robot = {
  energyLevel: 100,
  checkEnergy() {
    console.log(`Energy is currently at ${this.energyLevel}%.`)
  }
}

robot.checkEnergy();

4. Privacy : 정보 은닉

 객체를 사용하는 데 있어 프로퍼티에 접근하거나 프로퍼티를 업데이트하는 것은 필수적이다. 이때 외부에서 함부로 코드를 손상시키지 않도록 접근지정자를 사용하곤 한다. 한편 자바스크립트에서는 접근지정자를 제공하지 않기 때문에, 숨기고자 하는 프로퍼티 이름 앞에 언더바( _ )를 붙여 부적절한 접근을 차단할 의도를 표시하는 것이 관례적이다.

 아래 예시에서는 은닉할 프로퍼티의 이름을 특별히 언더바(_)를 사용하여 표시하였다.  하지만 여전히 객체 외부에서 접근가능하다는 한계가 있다.

const bankAccount = {
  _amount: 1000
}

bankAccount._amount = 1000000; // 여전히 접근가능

 다음 챕터에서 언더바를 붙여 숨겨둔 프로퍼티에 접근하는 방법으로, 프로퍼티의 값을 수정하는 getter 메서드와 값을 가져오는 setter 메서드를 알아보자.

Instruction

1. robot 객체의 _energyLevel 프로퍼티에 'high'를 새로 할당하라.

2. recharge 메서드는 _energyLevel 프로퍼티를 30 증가시킨다. 하지만 _energyLevel의 값이 숫자가 아니라면 어떨까? .recharge() 메서드를 호출해 확인하라. 1.과 같은 부적절한 접근을 통해 의도하지 않은 부작용이 발생할 수 있음을 알아두자.

const robot = {
  _energyLevel: 100,
  recharge(){
    this._energyLevel += 30;
    console.log(`Recharged! Energy is currently at ${this._energyLevel}%.`)
  }
};


robot._energyLevel='high';
robot.recharge(); // Output : Recharged! Energy is currently at high30%.

5. Getters : getter 메서드

 getter 메서드는 객체 내부의 프로퍼티의 값을 반환한다. 또한 단지 값을 반환하는 것뿐만 아니라 반환하려는 값이 적절한지 확인하는 단계를 추가할 수도 있다. 정확하게는 getter가 메서드의 이름은 아니며, get 예약어로 선언되어 이러한 동작을 수행하는 함수를 가리킨다.

 

아래 예시에서 getter 메서드인 fullName()의 특징을 살펴보자.

const person = {
  _firstName: 'John',
  _lastName: 'Doe',
  get fullName() {
    if (this._firstName && this._lastName){
      return `${this._firstName} ${this._lastName}`;
    } else {
      return 'Missing a first name or a last name.';
    }
  }
}
 
// To call the getter method: 
person.fullName; // 'John Doe'
  • get 키워드를 사용하여 함수를 정의하였다.
  • if...else 구문을 사용하여 _firstName과 _lastName의 값이 모두 존재하는지 확인한다.
  • this를 이용하여 해당 객체의 프로퍼티에 접근했다.
  • 마지막 줄에서 person 객체의 fullName을 호출하는 형태에 주목하라. 일반적으로 getter 메서드는 소괄호() 없이도 호출될 수 있다. 이는 구문적으로 우리가 프로퍼티에 직접 접근하는 것처럼 보이기도 한다.

주의할 것은 프로퍼티getter 또는 setter 함수동일한 이름을 공유할 수 없다는 점이다. 만약 동일하게 설정한 메소드를 호출하면 무한 호출 스택 오류가 발생한다. 프로퍼티 이름 앞에 밑줄을 추가하여 사용하도록 하자.

Instruction

1. get 예약어를 사용해 energyLevel이라는 이름을 가진 getter 메서드를 작성한다.

2. if문에서 typeof 연산자를 사용해 this._energyLevel이 숫자인지 검사한다. 참일 경우 'My current energy level is ENERGYLEVEL'를 리턴한다. 문자열 내의 ENERGYLEVEL을 this._energyLevel로 대체한다.

3. 위 if문의 조건이 거짓일 때 else를 사용하여 'System malfunction: cannot retrieve energy level'를 리턴한다.

4. robot.energyLevel을 콘솔에 출력한다.

const robot = {
  _model: '1E78V2',
  _energyLevel: 100,
  get energyLevel() {
    if (typeof(this._energyLevel)==='number'){
      return `My current energy level is ${this._energyLevel}`
    } else{
      return 'System malfunction: cannot retrieve energy level';
    }
  }
};

console.log(robot.energyLevel);

6. Setters : setter 메서드

 프로퍼티에 값을 재할당하는 setter 메서드를 작성하는 법을 알아보자. 정확하게는 setter가 메서드의 이름은 아니며, set 예약어로 선언되어 이러한 동작을 수행하는 함수를 가리킨다.

const person = {
  _age: 37,
  set age(newAge){
    if (typeof newAge === 'number'){
      this._age = newAge;
    } else {
      console.log('You must assign a number to age');
    }
  }
};

위 예시의 setter 메서드, age()를 살펴보자.

  • this._age에 값이 할당되었는지 검사한다.
  • this._age에는 숫자 값만이 재할당될 수 있다.
  • 새로 할당하려는 값에 따라 다른 출력문이 나온다.

setter 메서드를 사용하려면 다음과 같이 작성한다.

person.age = 40;
console.log(person._age); // Logs: 40
person.age = '40'; // Logs: You must assign a number to age

getter 메서드와 동일하게 setter 메서드는 소괄호() 없이도 호출될 수 있다. 이는 구문적으로 우리가 프로퍼티를 직접 수정하는 것처럼 보이기도 한다.

 

 여전히 ._age 프로퍼티에 직접적으로 접근할 수 있다는 한계는 있다.

person._age = 'forty-five'
console.log(person._age); // Prints forty-five

Instruction

1. set 키워드로 setter 메서드 numOfSensors를 정의하라. num을 매개변수로 설정한다.

2. setter 메서드는 typeof 연산자로 num이 숫자인지 확인하고, num이 0보다 크거나 같은지 확인한 후 두 조건을 모두 충족할 경우 this._numOfSensors에 num을 할당한다.

3. 위의 조건을 충족시키지 않는 경우에 대해서 else를 이용해 'Pass in a number that is greater than or equal to 0'를 출력하도록 한다.

4. numOfSensors를 이용해 100을 재할당해보라.

5. 메서드가 잘 동작했는지 확인하기 위해 콘솔에 robot.numOfSensors를 출력한다.

const robot = {
  _model: '1E78V2',
  _energyLevel: 100,
  _numOfSensors: 15,
  get numOfSensors(){
    if(typeof this._numOfSensors === 'number'){
      return this._numOfSensors;
    } else {
      return 'Sensors are currently down.'
    }
  },
  set numOfSensors(num){
    if (typeof(num)==='number' && num>=0){
      this._numOfSensors=num;
    } else{
      console.log('Pass in a number that is greater than or equal to 0');
    }
  }
  
};

robot.numOfSensors=100;
console.log(robot.numOfSensors);

7. Factory Functions : 팩토리 함수

 그동안 객체를 개별적으로 만들어왔지만, 수많은 객체를 빠르게 생성하고 싶을 때가 있다. 이때 팩토리 함수(factory function)를 사용할 수 있다. 공장(factory)에서 제품이 대량으로 생산되듯 팩토리 함수는 객체를 대량으로 만들어낼 수 있다.

 

const monsterFactory = (name, age, energySource, catchPhrase) => {
  return { 
    name: name,
    age: age, 
    energySource: energySource,
    scare() {
      console.log(catchPhrase);
    } 
  }
};

 

 팩토리 함수는 객체를 반환하는 함수를 만드는 것으로 정의할 수 있다. 아래는 monsterFactory 팩토리 함수를 이용해 정형화된 틀로 찍어낸 ghost 객체이다.

const ghost = monsterFactory('Ghouly', 251, 'ectoplasm', 'BOO!');
ghost.scare(); // 'BOO!'

Instruction

1. 팩토리 함수를 만들기 위해, 매개변수 model, mobile를 갖는 robotFactory 를 정의하라. 이 객체는 model 프로퍼티에 매개변수 model의 값을 할당받고, mobile 프로퍼티에 매개변수 mobile의 값을 할당받는다. beep() 메소드를 추가하여 'Beep Boop'를 출력하도록 한다.

const robotFactory = (model, mobile) => {
  
  return {model: model,
    mobile: mobile,
    beep(){
      console.log('Beep Boop');
    }
  }
};

2. 팩토리 함수를 이용해 tincan 객체를 만들어라. 첫 번째 인수로 'P-500', 두 번째 인수로 true를 넣어 생성한다.

const tinCan = robotFactory('P-500', true);

3. tinCan이 잘 만들어졌는지 확인하기 위해 .beep() 메서드를 호출한다.

tinCan.beep(); // Output : Beep Boop

8. Property Value Shorthand : 프로퍼티 값 간편하게 지정

 

const monsterFactory = (name, age) => {
  return { 
    name: name,
    age: age
  }
};

위 코드를 아래와 같이 쓸 수 있다. 매개변수가 리스트 순서대로 프로퍼티에 각각 대입되는 방식이다.

const monsterFactory = (name, age) => {
  return { 
    name,
    age 
  }
};

Instruction

1. 간편한 프로퍼티 지정법을 이용해 코드를 재작성하라.

const robotFactory = (model, mobile) => {
  return {
    model,
    mobile,
    beep() {
      console.log('Beep Boop');
    }
  }
};

9. Destructed Assignment : 구조 분해 할당

 

const vampire = {
  name: 'Dracula',
  residence: 'Transylvania',
  preferences: {
    day: 'stay inside',
    night: 'satisfy appetite'
  }
};

위 객체의 residence 프로퍼티를 변수로 이용하려면 일반적으로 다음과 같이 작성한다.

const residence = vampire.residence; 
console.log(residence); // Prints 'Transylvania'

한편 우리는 구조 분해 할당 방법으로 프로퍼티의 이름 자체를 변수로 바로 지정할 수 있다. 중괄호{ }를 이용해 작성한다.

const { residence } = vampire; 
console.log(residence); // Prints 'Transylvania'

객체 내부에 중첩된 객체의 프로퍼티 또한 지정할 수 있다.

const { day } = vampire.preferences; 
console.log(day); // Prints 'stay inside'

Instruction

1. const functionality에 robot의 fuctionality를 할당한다.

2. functionality가 robot.functionality를 참조하고 있기 때문에, 그 내부의 메소드를 이용할 수 있다. beep() 메소드를 호출한다.

const robot = {
  model: '1E78V2',
  energyLevel: 100,
  functionality: {
    beep() {
      console.log('Beep Boop');
    },
    fireLaser() {
      console.log('Pew Pew');
    },
  }
};

const {functionality} = robot;
functionality.beep();

10. Built-in Object Methods : 내장 객체 메소드

 앞서 객체들이 인스턴스로 생성된 메소드를 사용하는 것을 살펴보았다. 한편, 객체 자료형 자체에 내장된 메소드를 이용할 수도 있다.

  • 객체 내장 메서드 .hasOwnProperty(), .valueOf(),
  • Object 객체 내장 메서드 Object.assign(), Object.entries(), Object.keys()

자세한 사항은 아래 링크의 Object 인스턴스 문서를 참조하라.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object#Methods

Instruction

const robot = {
	model: 'SAL-1000',
  mobile: true,
  sentient: false,
  armor: 'Steel-plated',
  energyLevel: 75
};

1. Object.keys()는 프로퍼티를 배열로 리턴한다.

// What is missing in the following method call?
const robotKeys = Object.keys(robot);

console.log(robotKeys);
// Output : [ 'model', 'mobile', 'sentient', 'armor', 'energyLevel' ]

2. Object.entries()는 프로퍼티와 값이 쌍을 이루어 나열된 다차원 배열을 리턴한다.

// Declare robotEntries below this line:
const robotEntries = Object.entries(robot)
console.log(robotEntries);
/* Output : 
[ [ 'model', 'SAL-1000' ],
  [ 'mobile', true ],
  [ 'sentient', false ],
  [ 'armor', 'Steel-plated' ],
  [ 'energyLevel', 75 ] ]
*/

3. Object.assign()은 프로퍼티와 값의 쌍을 객체 선언식의 형태로 리턴한다. 사용 시 다음 문서를 확인하고 문법에 주의하라. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign#syntax

// Declare newRobot below this line:
const newRobot = Object.assign({laserBlaster: true, voiceRecognition: true}, robot);

console.log(newRobot);

/* Output :
{ laserBlaster: true,
  voiceRecognition: true,
  model: 'SAL-1000',
  mobile: true,
  sentient: false,
  armor: 'Steel-plated',
  energyLevel: 75 }
*/

Corner React Starter #2

Editor 숨숨

728x90

관련글 더보기