3 분 소요

객체지향 프로그래밍 (Object-Oriented Programming) : 원시 타입을 제외한 모든 것이 객체

자바스크립트는 프로토타입 (Prototype) 기반 객체지향 프로그래밍 언어 (LispSchemeJavaScript)

  • 객체 타입 (Object Type)과 클래스 (Class)를 통해 생성된 인스턴스 타입 (Instance Type) → this
  • 프로퍼티는 각 인스턴스의 EnvRec에 생성되고, 메소드는 프로토타입에 할당되어 모든 인스턴스가 동일
    • 특정 인스턴스에 종속되지 않는 함수는 정적인 클래스 메소드 (Class Method)
class Animal {}
class Dog extends Animal {}
const lucy = new Dog();

console.log(lucy instanceof Dog); // true
console.log(lucy instanceof Animal); // true
console.log(lucy instanceof Object); // true

console.log(Object.getPrototypeOf(lucy)); // Animal {}
console.log(Object.getPrototypeOf(Dog)); // [class Animal]
console.log(Object.getPrototypeOf(Animal)); // {}
  • 프로토타입은 단방향 LinkedList으로 연결된 구조 → 프로토타입 체인 (Prototype Chain)
    • 특정 프로퍼티에 접근할 때 해당 객체에 프로퍼티가 없으면, 내부 참조를 따라 상위 프로토타입을 순차적으로 검색

정적 필드 & 메소드 (Static Field & Method) : 특정 인스턴스와 무관하게 클래스에 존재하는 메소드

  • 인스턴스 프로퍼티를 참조할 수 없음 → Static 영역에 생성
class Animal {
  static ID = 1;
  static isDog(ani) {
    return ani.name === 'Dog';
  }
} 
const dog = new Animal('Dog');
dog.isDog(dog); // TypeError: dog.isDog is not a function
Animal.isDog(dog); // OK

싱글톤 패턴 (Singleton Pattern) : 어떤 클래스가 한 번만 인스턴스화되어, 그 인스턴스에 대한 전역 접근 제공

class Singleton {
  static #_instance; // 관례상 protected
  constructor() {
    if (Singleton.#_instance) return Singleton;
    this.name = 'Singleton';
    Singleton.#_instance = this;
  }

  static getInstance() {
    return this.#_instance || new this();
  }
}

const s1 = new Singleton();
const s2 = new Singleton();

접근자 (Accessor) 프로퍼티 : 특정 인스턴스와 무관하게 클래스에 존재하는 메소드

  • 접근자 프로퍼티을 통해 함수를 프로퍼티처럼 활용할 수 있음
class Emp1 {
  set fullName(name) { // set을 프로퍼티처럼 활용할 수 있음 → accessor
    [this.firstName, this.lastName] = name.split(' ');
  }
  
  get fullName() {  // get을 프로퍼티처럼 활용할 수 있음 → accessor
    return `${this.firstName} ${this.lastName}`;
  }
}

class Emp2 { // stackOverflow 발생!
  set name(nm) { this.name = nm; }
  get name() { return this.name; }
}

class Emp3 {
  #name;

  set name(#name) { this.#name = name; }
  get name() { return this.name; }
}

const hong1 = new Emp1();
hong1.fullName = 'Gil-Dong Hong';
console.log(hong1.fullName);

const hong2 = new Emp2();
hong2.fullName = 'Gil-Dong Hong';
console.log(hong2.fullName);

const hong3 = new Emp3();
hong3.fullName = 'Gil-Dong Hong';
console.log(hong3.fullName);

프록시 (Proxy) 객체 : 객체의 특정 동작을 가로채서 (Hooking)해서 추가 동작 수행

  • 객체의 작업에 대한 기록 → 로깅 (Logging)
  • 잘못된 접근에 대한 오류 (Validation Check)
  • 기능 제어 (읽기 전용 등) 및 객체 정보 숨기기
const obj = {
  id: 1,
  name: 'Hong',
  f() {
    console.log('fffff')
  },
};

export const objProxy = new Proxy(obj, {
  set(target, prop, value){
    console.log('proxy.set>>', prop, value);
    target[prop] = value;
  },
  get(target, prop){
    console.log('proxy.get >> ', prop);
    return target[prop];
  },
});

objProxy.id = 100;
console.log('obj.id>>', objProxy.id, obj['id']);

상속 (Inheritance) : SubClass가 프로토타입 체인으로 Superclass의 모든 데이터와 기능을 상속

class Dog extends Animal {
  constructor(name) {
    super(name); // 필수(for chaining) + 중복(overload) 불가!
  }

  bark() {
    console.log('bowwow!');
  }
}
  • 모든 객체는 프로토타입 체인 (__proto__) 이라는 내부 속성을 가짐
    • 객체를 생성하는 생성자 함수는 prototype 속성을 가짐 → 해당 프로토타입이 객체의 프로토타입가 됨
    • 하위 객체는 상위 객체의 프로토타입을 따라 상위 객체의 속성 및 메소드를 탐색

스택 (Stack) & 큐 (Queue) : 데이터를 저장하고 관리하기 위한 자료구조

class Stack { // 스택 자료구조
    collection = [];

    push(value) {
        this.collection.push(value);
    }
    pop() {
        return this.collection.pop();
    }
}

const stack = new Stack();
stack.push(1); // 추가하기
stack.push(2); // 추가하기
stack.push(3); // 추가하기
console.log(stack.pop()) // 마지막으로 추가된 하나 꺼내기

class Queue { // 큐 자료구조
    collection = [];

    enqueue(value) {
        this.collection.push(value);
    }

    dequeue() {
        return this.collection.shift();
    }
}

const queue = new Queue();
queue.enqueue(1); // 추가하기
queue.enqueue(2); // 추가하기
queue.enqueue(3); // 추가하기
console.log(queue.dequeue()) // 마지막으로 추가된 하나 꺼내기


메소드 오버라이딩 (Method Overriding) : 자식 클래스가 부모 클래스의 메소드를 재정의

class Animal {
  ...
  id = 1;       // 멤버 프로퍼티
  #age = 10;    // 멤버 프로퍼티 (protected)
  
  toString() {  // 객체의 toString() 오버라이딩 ([메소드] 다형성!)
    return `This animal's name is ${this.name}.`;
  }
} 

다중 상속 (Multiple Inheritance) : 한 클래스가 여러 클래스들을 상속

  • 자바스크립트는 단일 상속 언어 → Mixin을 통해 제한적으로 구현할 수 있음 (타입스크립트 : Interface)
// Mixin 정의
const myMixin = {
  sayHello() {
    console.log("Hello!");
  },
  sayGoodbye() {
    console.log("Goodbye!");
  },
};

function MyClass() {
  ... // 클래스의 생성자 로직
}

Object.assign(MyClass.prototype, myMixin); // Mixin 적용

const obj = new MyClass(); // 객체 생성 및 Mixin 메서드 호출
obj.sayHello();    // 출력: Hello!
obj.sayGoodbye();  // 출력: Goodbye!

태그:

업데이트: