Skip to content

Latest commit

 

History

History
166 lines (131 loc) · 4.45 KB

25장_클래스.md

File metadata and controls

166 lines (131 loc) · 4.45 KB

#1 static method와 prototype method 차이

prototype method는 인스턴스에서 직접 호출이 가능하나, static method는 생성자 함수를 this로 해야만 호출할 수 있다.

var Person = function (name, age) {
  this.name = name;
  this.age = age;
};

// prototype method -> prototype chaining에 의한 참조
Person.prototype.getIntroduce = function () {
  return `hello my name is ${this.name}, and i'm ${this.age}`;
};

// static method
Person.getNameAndAge = function (name, age) {
  return name + " : " + age;
};

var p = new Person("seoin", 27);
console.log(p.getIntroduce());
// console.log(p.getNameAndAge("seoin", 27)); -> error
console.log(Person.getNameAndAge("seoin", 27));

#2 ES6 클래스

내장 명령으로 손쉽게 클래스 구현이 가능하다

class 키워드를 이용하고 상위 클래스는 extends 키워드를 이용해 상속한다.

class Person {
  constructor(name, age) {
    this.name = name || "이름없음";
    this.age = age || "나이모름";
  }

  getName() {
    return this.name;
  }

  getAge() {
    return this.age;
  }
}

class Saram extends Person {
  constructor(name, age, address) {
    super(name, age);
    this.address = address || "지역모름";
  }

  getAddress() {
    return this.address;
  }
}

#추가 : ES5에서 클래스를 구현하기

ES5까지 클래스가 없었고, ES6에 도입됐다. ES5에서 클래스를 구현하려면 어떻게 해왔을까를 예로 들어 봤다. (면접 질문으로 나올 거 같진 않다.)

var Person = function (name, age) {
  this.name = name || "이름없음";
  this.age = age || "나이모름";
};

// prototype method
Person.prototype.getName = function () {
  return this.name;
};

Person.prototype.getAge = function () {
  return this.age;
};

function Saram(name, age, address) {
  this.name = name || "이름없음";
  this.age = age || "나이모름";
  this.address = address || "지역모름";
}
// 인스턴스의 프로토타입에 상위 객체의 인스턴스를 할당
// 기존에 있던 Saram.prototype은 사실상 새로 대체
// 프로토타입 객체는 js 엔진이 기본적으로 constructor  프로퍼티를 생성해주고, 그 안에 생성자 함수가 담김
// -> constructor 재정의 필요
Saram.prototype = new Person();
Saram.prototype.constructor = Saram;
Saram.prototype.getAddress = function () {
  return this.address;
};

var s1 = new Saram("seoin", 27, "seoul");
console.dir(s1);

문제 -> 프로토타입 체인 상에 프로퍼티가 아닌 메소드만 존재하게 하는게 나음

→ 인스턴스에서 name, age 프로퍼티 삭제하고 getName, getAge 호출 시 체인을 타고 원하지 않은 결과를 출력

// 불필요한 프로퍼티 삭제하고 싶음 -> 중간에 비어 있는 생성자 함수를 넣어 연결
function Bridge() {}
Bridge.prototype = Person.prototype;
Saram.prototype = new Bridge();
Saram.prototype.constructor = Saram;
Saram.prototype.getAddress = function () {
  return this.address;
};

var s2 = new Saram("seoin", 27, "seoul");
console.dir(s2);

위의 방식이 ES5에서 클래스 상속을 구현하려 할 때 많이 등장하는 패턴이라고 함

Bridge 함수는 매개체 역할만 할 뿐, 실제 코드 상에서는 영향을 주지 않음

더글라스 크락포드 → 함수화 추천

var extendClass = (function () {
  function Bridge() {}
  return function (Parent, Child) {
    Bridge.prototype = Parent.prototype;
    Child.prototype = new Bridge();
    Child.prototype.constructor = Child;
  };
})();

위와 같이 클로저를 이용해 Bridge 생성자 함수는 한 번만 생성해 계속 재활용 하고, super와 sub 클래스로 쓰일 생성자 함수를 매개변수로 넘겨주면, 자동으로 둘 사이의 상속 구조를 구현할 수 있음

extendClass(Person, Saram);
Saram.prototype.getAddress = function () {
  return this.address;
};

var s3 = new Saram("seoin", 27, "seoul");
console.dir(s3);

메서드 상속에 이어 인스턴스의 value까지 상속을 이용한다면, 아래와 같이 쓸 수 있다.

var extendClass = (function () {
  function Bridge() {}
  return function (Parent, Child) {
    Bridge.prototype = Parent.prototype;
    Child.prototype = new Bridge();
    Child.prototype.constructor = Child;
    Child.prototype.superClass = Parent;
  };
})();

function Saram(name, age, address) {
  this.superClass(name, age);
  this.address = address || "지역모름";
}