(1) 원시적인 클래스(빈) 객체 생성 및 객체 인스턴스화
(2) class 를 이용한 클래스 객체 생성 및 객체 인스턴스화
원시적인 클래스(빈) 객체 생성 및 객체 인스턴스화
function CartV1() { // 원시적인 빈객체(원시 클래스)
  this.cart = [];   // 변수 초기화
  this.currentId = 0;
}
CartV1.prototype.getNewId = function () { // method
  this.currentId++;
  return this.currentId;
};
CartV1.createItem = function (name, price) { // == static method
  return {
    name,
    price,
  };
};
CartV1.prototype.addItem = function (item) { // method
  this.cart.push({
    ...item,
    id: this.getNewId(),
  });
};
CartV1.prototype.clearCart = function (item) { // method
  this.cart = [];
  this.currentId = 0;
};
const shoppingCartV1 = new CartV1(); 
// new 사용으로 CartV1 이라는 빈객체 생성 (인스턴스화)
shoppingCartV1.addItem(CartV1.createItem('사과', 8000));
shoppingCartV1.addItem(CartV1.createItem('수박', 12000));
shoppingCartV1.addItem(CartV1.createItem('두부', 2000));
console.log(shoppingCartV1.cart);
class 를 이용한 클래스 객체 생성 및 객체 인스턴스화
class CartV2 {
  cart;
  currentId;
  constructor() { // 변수 초기화
    this.cart = [];
    this.currentId = 0;
  }
  getNewId = () => { // method
    this.currentId++;
    return this.currentId;
  }
  static createItem = (name, price) => { // static method
    return {
      name,
      price,
    }
  }
  addItem = (item) => { // method
    this.cart.push({
      ...item,
      id: this.getNewId(),
    });
  }
  clearCart = () => { // method
    this.currentId = 0;
    this.cart = [];
  }
}
const shoppingCartV2 = new CartV2(); 
// new 사용으로 CartV2 이라는 클래스 객체 생성 (인스턴스화)
shoppingCartV2.addItem(CartV2.createItem('사과', 8000));
shoppingCartV2.addItem(CartV2.createItem('수박', 12000));
shoppingCartV2.addItem(CartV2.createItem('두부', 2000));
console.log(shoppingCartV2.cart);
// [
//   { name: '사과', price: 8000, id: 1 },
//   { name: '수박', price: 12000, id: 2 },
//   { name: '두부', price: 2000, id: 3 }
// ]
// 두 객체의 결과는 동일
const c1 = {
  name: 'C1',
  color: 'red',
};
const c2 = {
  name: 'C2',
  width: 300,
};
const c3 = {
  name: 'C3',
  hetght: 100,
};
console.log(c1); // { name: 'C1', color: 'red' }
console.log(c2); // { name: 'C2', width: 300 }
console.log(c3); // { name: 'C3', hetght: 100 }
c1.__proto__ = c2; // c2를 c1에 상속
c2.__proto__ = c3; // c3를 c2에 상속
console.log(c1.__proto__); // c2
console.log(c2.__proto__); // c3
console.log(c1.width); 
// c1에서 width를 찾고 없으면 상위 (__proto__: c2) 인 c2 에서 width를 찾게된다.
proto => 해당 객체의 상위 객체의 개념
prototype => 객체에 프로퍼티를 추가할 수 있는 예약어 / 현재 객체의 속성 및 메소드들
function Foo(name) {
  this.name = name;
  this.__proto__ = Foo.prototype; 
  // lastName은 Foo객체와 Foo객체의 상위인 __proto__ 에도 존재하게 된다.
}
Foo.prototype.lastName = 'HeeT';
const f = new Foo('Kim');
console.log(f); // Foo { name: 'Kim' }
console.log(f.lastName); // HeeT
console.log(f.__proto__.lastName); // HeeT
console.log(Foo.prototype); // { lastName: 'HeeT' }