1. 객체가 무엇인가요?


1-1. 객체는 현실세계를 표현하기 위한 데이터와 함수의 집합입니다.

  • 현실세계에서 볼 수 있고, 만질 수 있고, 상상할 수 있고, ... 등등 인지할 수 있는 모든 것(현실세계 객체)들을 프로그래밍 세계로 옮겨와 표현하기 위한 개념입니다.
  • 객체의 데이터는 프로퍼티(property)라고 부릅니다.
  • 객체의 동작을 표현하는 함수를 메소드(method)라고 합니다.
  • 객체의 본질은 내용물을 담는 컨테이너입니다.
  • 컨테이너의 내용물은 시간이 지나면서 바뀔 수 있지만, 그렇다고 해서 컨테이너 자체가 바뀌는 것은 아닙니다.

2. 객체를 만드는 방법에는 어떤 것들이 있나요?


2-1. 객체 리터럴(object literal)

const coffeeMachine = {              // coffeeMachine 객체리터럴 생성
    // 프로퍼티
    modelName: 'daf-123',
    menu: ['americano', 'latter', 'herbal tea'],
    machineManager: 'park',
    coffeeBean: {                    // 객체도 프로퍼티 가능
        name: 'robusta',
        origin: 'west africa',
        price: 100
    },
    // 메소드
    makeCoffee: function() {
        console.log(`${this.menu[1]}가 완성되었습니다.`);
    },
    getmodelname() {                     // ES6에서는 이렇게 메서드를 추가할 수 있는 문법이 생겼습니다.
        console.log(`${this.modelName}`);
    }
};
console.log(coffeeMachine.machineManager);        // 'park' 출력, 점 연산자 사용
console.log(coffeeMachine['machineManager']);     // 'park' 출력, 대괄호 사용
console.log(coffeeMachine['coffeeBean'].price);   // 100 출력
coffeeMachine.makeCoffee();                       // 'latte가 완성되었습니다.' 출력
coffeeMachine.getmodelname();                     // 'daf-123' 출력
  • 객체 리터럴 문법에서는 객체를 만드는 동시에 프로퍼티와 메소드를 만들 수 있습니다.
  • 프로퍼티의 이름은 반드시 문자열 또는 심볼이어야 하지만, 값은 어떤 타입이든 상관없습니다.
  • 이 프로퍼티는 키(key)와 값(value)으로 구성됩니다.
  • 객체의 프로퍼티에 접근하기 위해서는 점 연산자대괄호를 사용할 수 있습니다.
    • 대괄호를 사용하면 프로퍼티 이름에 작은따옴표나 큰따옴표를 씌워야합니다.

2-2. contructor

  • 함수를 선언한 다음 new 키워드로 객체를 생성하는 방법입니다.

  • 새로운 객체를 생성할 때마다 객체의 메소드가 매번 새로 생성되므로 비효율적입니다.


2-3. prototype pattern

const CoffeeMachine = function (menu, price) {
    this.menu = menu;
    this.price = price;
};

CoffeeMachine.prototype.makeCoffee = function () {
    console.log(`${this.menu}가 완성되었습니다.`);
};

const coffee = new CoffeeMachine('lette', 100);
  • 생성자를 통해 생성된 인스턴스들이 여러개 있어도, prototype에 연결된 인스턴스들은 동일한 메모리 공간에서 효율적으로 재사용됩니다.
  • prototype 객체는 최상위 object까지 연결되어 있습니다. 그러므로 prototype 연결고리를 만들어서 객체간 상속관계를 만들 수 있습니다.

2-4. Object.create


2-5. ES Classes pattern - ES6

  • 클래스는 함수입니다.

3. 왜 클래스를 사용하나요?

  • 여러개의 객체를 생성할 필요가 없을 경우에는 object literal로 원하는 객체를 1개씩 만들어 사용합니다.
  • 특정 구조의 객체를 여러곳에서 사용해야 하는 경우 클래스로 필요할 때마다 인스턴스를 생성하면 재사용성, 유지보수 편리함 등 장점이 있습니다.

4. 더 공부해볼 부분들

4-1. Symbol?


4-2. prototype?

const CoffeeMachine = function (menu, price) {
    this.menu = menu;
    this.price = price;
};

CoffeeMachine.prototype.makeCoffee = function () {
    console.log(`${this.menu}가 완성되었습니다.`);
};

CoffeeMachine.prototype.getPrice = function () {
    console.log(`${this.price}`);
}

const coffee = new CoffeeMachine('lette', 100);
const coffee2 = new CoffeeMachine('americano', 50);
coffee.getPrice();
coffee.makeCoffee();

console.log(coffee.__proto__ === coffee2.__proto__);       // true 출력
// 같은 클래스에서 생성된 인스턴스들은 같은 프로토타입을 공유
console.log(coffee.__proto__ === CoffeeMachine.prototype); // true 출력
// coffee 오브젝트의 __proto__ 프로퍼티에 CoffeeMachine 클래스의 getPrice(), makeCoffee() 메소드 저장됨.
console.log(coffee.getPrice === coffee2.getPrice);         // true 출력
coffee2.getPrice();                                        // 50출력
coffee2.getPrice = function () {
    console.log('coffee2의 getPrice 메소드 재정의 함.');
};
console.log(coffee.getPrice === coffee2.getPrice);          // false 출력 
// coffee2 인스턴스 안에서 프로토타입의 메소드와 동일한 이름의 메소드를 정의하면 프로토타입의 메소드는 가려지고 인스턴스의 메소드가 호출된다.
coffee2.getPrice(); // 'coffee2의 getPrice 메소드 재정의 함.' 출력
  • 모든 함수에는 prototype이라는 특별한 프로퍼티가 있습니다.

  • 객체 생성자로 동작하는 함수에서는 prototype이 매우 중요합니다

  • new 키워드로 만든 새 객체는 생성자의 prototype 프로퍼티에 접근할 수 있습니다.

  • 객체 인스턴스는 생성자의 prototype 프로퍼티를 __proto__프로퍼티에 저장합니다.
    prototype.PNG

  • 객체의 프로퍼티나 메소드에 접근하려 할 때 만약 객체에 찾는 프로퍼티나 메소드가 없다면 객체의 프로토타입에서 해당 프로퍼티나 메소드를 찾습니다.

  • 같은 클래스에서 생성된 객체 인스턴스들은 모두 같은 프로토타입을 공유합니다.

  • 자바스크립트는 먼저 인스턴스에서 원하는 프로퍼티나 메소드를 탐색하고, 없다면 프로토타입에서 찾기 때문에, 인스턴스에서 프로퍼티나 메소드를 정의하면 프로토타입에 있는 것을 가리는 효과가 있습니다.


4-3. 상속?


참고자료