상세 컨텐츠

본문 제목

[Javascript] 08. Objects

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

by Kimpeep 2022. 9. 22. 10:07

본문

728x90

8. Objects

8-1.  Objects 

객체를 배우다보면 생각보다 배우지 않았는데도 익숙할 것입니다. 객체는 자바스크립트에 많은 곳에 사용되고 있어서 배우지 않아도 사용을 하고 있었기 때문에 익숙했을 것입니다. 자바스크립트에서 다루는 데이터의 유형은 총 7개인데, string, number, boolean, null, undefined, symbol이고 마지막으로 Object가 있습니다. 이번에는 마지막 유형인 Objects, 객체에 대해서 다룰 것입니다.



8-1-1. Creating Object Literals

객체는 다른 자바스크립트 유형과 같이 변수에 할당할 수 있습니다. 객체 리터럴을 지정하기 위해서는 중괄호 {}를 사용합니다. 

let spaceship = {}; // spaceship is an empty object


위의 예시를 보면 객체 안에는 비어있는 객체입니다. 이 객체에 데이터를 채우기 위해서는 키-값 쌍으로 조직화하여 작성해야 합니다. 키는 값이 있는 메모리의 위치를 가리킵니다. 키의 값은 함수를 포함하여 모든 데이터의 유형일 수 있습니다. 

let spaceship = {
  'Fuel Type': 'diesel',
  color: 'silver'
};


spaceship 객체는 키-쌍의 형태로 데이터가 채워졌습니다. 키는 키의 이름, 식별자로 작성합니다. 즉, 'Fuel Type', color가 키에 해당이 됩니다. 콜론(;)을 작성하여 값을 작성해줍니다. 'diesel', 'silver'가 값에 해당이 됩니다. 객체 안에서 키-쌍은 쉼표(,)로 구분을 합니다. 키는 문자열로 작성은 하지만 특별하지 않은 경우에는 따옴표를 생략을 할 수 있습니다. 

8-1-2. Accessing Properties

객체의 속성에 접근을 하는 방법에는 두가지가 있습니다. 첫 번째 방법은 .을 이용한 점 표기법입니다. 

let spaceship = {
  homePlanet: 'Earth',
  color: 'silver'
};

spaceship.homePlanet; // Returns 'Earth',
spaceship.color; // Returns 'silver',
spaceship.favoriteIcecream; // Returns undefined


spaceship 객체 안에 있는 homePlanet라는 속성을 접근하기 위해 객체 이름 뒤에 .을 작성하고 그 뒤에 속성의 이름(키의 이름)을 작성해주면 됩니다. 이때 객체에 존재하지 않은 속성에 접근을 하려고 하면 'undefined'을 반환하게 됩니다.  

8-1-3. 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['!!!!!!!!!!!!!!!'];   // Returns undefined


 아래의 예시와 같이 함수와 함께 사용할 때 유용할 것입니다. 

let returnAnyProp = (objectName, propName) => objectName[propName];
 
returnAnyProp(spaceship, 'homePlanet'); // Returns 'Earth'


점 표기법을 이용해서 objectName.propName로 작성하면 컴퓨터는 propName 매개변수 값이 아니라 객체에서 'propName'이름을 가진 키를 찾게 될 것입니다.

8-1-4. Property Assignment

객체를 한번 정의를 하고 나면 객체는 변경이 가능하므로 업데이트를 할 수 있습니다. 점(.)표기법이나 괄호([])표기법과 할당 연산자(=)를 이용해서 키-값 쌍을 추가할 수도 있고 기존의 있었던 속성을 변경할 수 있습니다. 

출처 Codecademy

괄호표기법과 할당연산자를 둘을 활용하여 값을 변경할 수도 있고 점 표기법을 활용하여 변경을 할 수 있습니다. 이런 속성 할당할 시 다음과 같은 사례가 발생할 수 있습니다.

  • 객체에 이미 속성이 있는 경우, 해당 속성이 가진 값이 무엇이든 간에 새로운 값으로 변경이 됩니다.
  • 같은 이름의 속성이 없으면, 새 키-쌍이 객체에 추가가 됩니다. 
const spaceship = {type: 'shuttle'};

spaceship.type = 'alien'; // Changes the value of the type property
spaceship.speed = 'Mach 5'; // Creates a new key of 'speed' with a value of 'Mach 5'

delete spaceship.type;  // Removes the type property


const로 선언된 객체는 재할당을 할 수는 없지만, 새로운 속성을 추가하거나 속성을 변경하는 것은 가능합니다. 그리고 delete를 이용항 객체에 있는 속성을 없앨 수도 있습니다. 

8-1-5. Methods

객체에 저장이 된 데이터가 함수일 때 우리는 <span style="background-color: lightgrey"> 메서드</span> 라고 부릅니다. 속성이 객체가 가지고 있는 것이라면 메서드는 객체가 하는 행동을 의미합니다. 혹시 메서드가 익숙하신가요? 그 이유는 계속 사용을 하고 있었기 때문입니다. console은 전역 자바스크립트 객체이고 .log()가 console 객체의 메서드입니다. 

우리는 쉼표로 구분된 키-쌍의 형태로 메서드를 객체 안에 포함시킬 수 있습니다. 키는 메서드의 이름으로 하고 값은 함수의 식으로 하여 메서드를 작성해줍니다. 

const alienShip = {
  invade: function () { 
    console.log('Hello! We have come to dominate your planet. Instead of Earth, it shall be called New Xaculon.')
  }
};

// 콜론(:)과 function 라는 키워드를 생략하는 것이 가능합니다 
const alienShip = {
  invade () { 
    console.log('Hello! We have come to dominate your planet. Instead of Earth, it shall be called New Xaculon.')
  }
};

alienShip.invade();


객체 메서드는 객체이름에 .작성하고 메서드의 이름과 괄호를 이용하여 호출할 수 있습니다. 

8-1-6. 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.nanoelectronics['back-up'].battery;


spaceship 객체 안에 telescope, crew, engine, nanoelectronics 라는 객체가 있고 각 객체 안에 여러 속성과 메서드가 있습니다. 이런 중첩 객체에 경우 속성을 접근하는 방법을 알아보겠습니다. battery에 접근을 하고 싶다면 spaceship이라는 객체 안에 nanoelectronics 객체 안에 'back-up' 객체 안에 battery의 순서로 접근하면 됩니다. 

8-1-7. Pass By Reference

객체는 참조를 전달이 됩니다. 이것은 객체에 할당된  변수를 함수의 인수로 전달을 하면 컴퓨터는 매개변수 이름을 객체가 있는 메모리 공간을 가리키는 것을 의미합니다. 그렇기에 객체 속성을 변경하는 함수는 객체를 영구적으로 변이합니다.

const spaceship = {
  homePlanet : 'Earth',
  color : 'silver'
};
 
let paintIt = obj => {
  obj.color = 'glorious gold'
};
 
paintIt(spaceship);
 
spaceship.color // Returns 'glorious gold'


위에 paintIt 함수에 객체를 전달을 하였고 spaceship 객체의 속성인 color를 변경했습니다. 

8-1-8. Looping Through Objects

반복문은 조건이 충족할 때까지 블록안에 있는 코드를 계속 반복하는 프로그래밍 도구입니다. 우리는 이전에 배열을 반복할 수 있는 반복자에 대해 배운적이 있습니다. 객체도 for...in 를 통해 반복을 할 수 있습니다. for(속성 in 객체){행동}의 구조로 사용이 됩니다. 다음 예시는 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...in
for (let crewMember in spaceship.crew) {
  console.log(`${crewMember}: ${spaceship.crew[crewMember].name}`);
}

 



8.Objects

8-2. Advanced Objects



8-2-1. The this Keyword

객체는 데이터와 기능의 모음집입니다. 기능은 객체의 메서드에 저장할 수 있습니다. 

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

goat.makeSound(); // Prints baaa


위의 코드를 보면 goat객체에 .makesound() 라는 메서드가 있습니다. 

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


.diet()라는 새 메서드를 염소 객체에 추가하려고 했지만 dietType goat 객체의 속성임에도 불구하고 diet() 에서는 정의되지 않았다고 나옵니다. 그 이유는 .diet() 메서드는 goat 객체의 다른 속성을 자동으로 액세스를 할 수다 없기 때문입니다. 이때 this라는 키워드를 사용하면 문제는 금방 해결됩니다.

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


this를 사용하면 객체 속성에 대한 접근이 가능해집니다. 

8-2-2. Arrow Functions and this

메소드에서 this를 사용하면 this의 값이 호출이 된 객체가 됩니다. 하지만 this 키워드를 화사표 함수에 사용하려면 조금 복잡해집니다. 

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


this 키워드를 사용을 했음에도 불구하고 정의되지 않았다는 것을 확인할 수 있습니다. 화살표 함수는 기본적으로 호출 객체가 아닌 함수 자체에 연결합니다. 따라서 this 값은 전역 객체 또는 전역 범위에 존재하는 객체이며, dietType 유형 속성이 없으므로 정의되지 않은 값으로 반환합니다. 

화살표 함수에 대해 더 알아보기 위해서 아래의 링크를 통해 참고해도 좋습니다.

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

 

Global object - MDN Web Docs Glossary: Definitions of Web-related terms | MDN

A global object is an object that always exists in the global scope.

developer.mozilla.org

8-2-3. Privacy

속성에 접근하고 속성을 업데이트를 하는 것은 객체를 사용하는데에 있어서는 필수적입니다. 그렇지만 객체 속성에 접근하고 속성을 업데이트를 하는 것을 원하지 않는 경우도 있습니다. 특정 언어에서는 객체에 대한 정보가 내장이 되어 있지만 Javascript에는 이런 기능이 없습니다. 자바스크립트 개발자들은 다른 개발자들에게 속성 이름 앞에 _ 을 지정하여 속성이 변경되지 않아야 함을 알려줍니다.  

const bankAccount = {
  _amount: 1000
}


_ 를 사용하여 amount는 직접적으로 조작이 될 수 없게 예정해놓은 상태입니다.

bankAccount._amount = 1000000;


하지만 위에서 코드처럼 _ 있어도 재할당하는 것은 가능하기는 합니다. 

8-2-4. Getters

Getters는 객체의 내부 속성을 가져와서 반환을 하는 메서드입니다. 

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'

 

  • Getter는 속성을 가져올 때 데이터에 대한 작업을 수행할 수 있습니다.
  • Getter는 조건을 이용하여 다른 값을 반환할 수 있습니다.
  • Getter는 this를 사용하여 호출 객체의 속성에 접근할 수 있습니다. 
  • 코드를 다른 개발자들이 문법적으로 더 쉽게 이해할 수 있게 합니다.

한가지 주의해야 할 점은 속성이 getter 함수와 동일한 이름을 공유할 수는 없습니다. 만약에 그럴 경우 계속 무한 호출을 하는 오류가 나기 때문입니다. 이를 해결하기 위해서는 속성 이름 앞에 밑줄을 추가해주면 됩니다. 

8-2-5. Setters

Getter 메서드와 더불어 기존의 속성의 값을 재할당하는 Setter 메서드를 만들 수 있습니다. 

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

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


위의 코드에서 age 앞에 _ 가 붙음으로서 변경이 불가한 상태입니다. 그러나 setter 메서드로 정의하여 _age 가 37에서 40으로 변한 것을 확인할 수 있습니다. 

Getter 메서드와 마찬가지로 입력 확인, 속성에 대한 작업을 수행하는 등의 장점이 있습닌다. 또한 Setter 를 사용하면 밑줄로 시작한 속성을 직접 재할당하는 것이 가능합니다. 

8-2-6. Factory Functions

지금까지는 객체를 개별적으로 생성했지만, 여러 객체 인스턴스를 빠르게 생성하고 싶을 때가 있습니다. 이럴 때 우리는 팩토리 함수를 사용합니다. 

팩토리 함수는 객체를 반환하는 함수이며 여러 객체 인스턴스를 만드는데 사용이 됩니다. 팩토리함수에는 객체를 반환해야 하기에 매개변수가 필요할 수도 있습니다. 

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

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


monsterFactory라는 함수를 통해 ghost 객체를 빠르게 만들어 낼 수 있을 것입니다. 함수에 인수만 전달하면 수많은 몬스터를 한번에 만들어내는 것이 가능해집니다.

8-2-7. Property Value Shorthand

팩토리함수를 만드는데 더 많은 속성을 포함해야 한다면 그 과정이 복잡해질 수 있을 것입니다. 속성 값 요약이라는 기술을 통해 키 입력을 줄일 수 있습니다. 

// 속성 값 요약을 적용하지 않은 상태
const monsterFactory = (name, age) => {
  return { 
    name: name,
    age: age
  }
};
// 속성 값 요약을 적용한 상태
const monsterFactory = (name, age) => {
  return { 
    name,
    age 
  }
};


위의 예시처럼 속성 할당을 반복할 필요없음을 알아 두세요!

8-2-8. Destructured Assignment

우리는 종종 객체에서 키-값 쌍을 추출하여 변수로 저장하는 경우가 있습니다.

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

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

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


위의 코드를 보면 같은 결과값을 출력함을 볼 수 있습니다. 두 번째는 비구조화 할당이라는 구조화 기술을 사용하여 키 입력을 절약을 했습니다. 중괄호 {}로 묶인 객체의 키 이름을 변수로 만들고 이 변수에 객체를 할당했습니다. 

8-2-9. Built-in Object Methods

이전에는 자신이 만든 메서드가 있는 객체 인스턴스를 만들어 왔습니다. 그러나 기본으로 제공하는객체에 대한 내장 메소드를 활용할 수 있습니다! 예를 들면, .hasOwnProperty(), .valueOf() 등과 같은 객체 인스턴스 메서드를 활용할 수 있습니다. 아래의 링크들을 통해 더 많은 메서드를 볼 수 있습니다.

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

 

Object - JavaScript | MDN

The Object type represents one of JavaScript's data types. It is used to store various keyed collections and more complex entities. Objects can be created using the Object() constructor or the object initializer / literal syntax.

developer.mozilla.org

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

 

Global object - MDN Web Docs Glossary: Definitions of Web-related terms | MDN

A global object is an object that always exists in the global scope.

developer.mozilla.org


JAVASCRIPT

Editor : 리미

728x90

'22-23 > 22-23 리액트 스타터 2' 카테고리의 다른 글

[리액트스타터2] 2장. JSX  (1) 2022.09.29
[리액트스타터2] 1장. 리액트 시작  (1) 2022.09.29
[Javascript] 07. Itereators  (0) 2022.09.22
[JavaScript] 06. Loops  (0) 2022.09.22
[JavaScript] 05. Arrays  (0) 2022.09.22

관련글 더보기