Javascrpit prototype으로Inheritance(상속) 하기

김현진·2020년 5월 10일
0

javascript의 prototype 상속방법에 대해서 살펴보겠습니다.

자바스크립트에서 상속은 한 객체의 메소드 / 속성을 다른 객체를 통해 사용할 수 있다는 개념을 설명합니다.

코드를 작성해보겠습니다.

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

Person.prototype.information = function() {
  console.log(`name: ${this.name} age: ${this.age}`);
} 

let human = new Person('james', 33);
console.log(human) // Person {name: "james", age: 33}

Student라는 생성자 함수를 생성해보겠습니다.

function Student(name, age, grade) {
  this.name = name;
  this.age = age;
  this.grade = grade;
}

Student.prototype.information = function() {
  console.log(`name: ${this.name} age: ${this.age}`);
}
let student1 = new Student('curry', 15, 'B');

console.log(student1); //Student {name: "curry", age: 15, grade: "B"}

Person 함수의 내용이랑 중복되는 부분이 있는걸 확인 할 수 있습니다.

this.name = name;
this.age = age;
Student.prototype.information = function() {
  console.log(`name: ${this.name} age: ${this.age}`);
}

이 중복을 없애고 간단하게 표현해보겠습니다.

function Student(name, age, grade) {
  Person.call(this,age,grade);
  this.grade = grade;
}
let student1 = new Student('curry', 15, 'B');
console.log(student1); // Student {name: "curry", age: 15, grade: "B"}
student1.information() // TypeError: student1.introduce is not a function

Person.call(this,age,grade)를 추가하여 Person을 속성값을 상속을 받았습니다.
student1.information()를 실행하니 TypeError가 발생하는걸 볼 수 있습니다.

그림으로 간략히 표현한다면


우선 student1의 속성에 information 메소드가 있는지 확인을 한다음 없다면 프로토를 통해 Student.prototype 을 확인을 할 것입니다.
하지만 Student.prototype에도 없으니 에러가 발생을 한 거 같네요.!!!

그렇다면 어떻게 할 지 보겠습니다.

function Student(name, age, grade) {
  Person.call(this,age,grade);
  this.grade = grade;
}

Student.prototpye.checkGrade = function() {
  console.log(` name: ${this.name} age: ${this.age} grade: ${this.grade}`)
}

Student.prototype = Person.prototype; // 상속을 위해 추가

let student1 = new Student('curry', 15, 'B');
console.log(student1); // Student {name: "curry", age: 15, grade: "B"}
student1.information(); // name: curry age: 15

정상적으로 나오는 걸 확인 할 수 있습니다.

그러나 Student 객체에 메소드를 추가를 했을때 어떻게 되는지 한번 보겠습니다.

function Person(name, age) {
    this.name = name;
    this.age = age;
  }
  
  Person.prototype.information = function() {
    console.log(`name: ${this.name} age: ${this.age}`);
  } 
  
  function Student(name,age, grade) {
      Person.call(this,name,age);
      this.grade = grade;
  }
  Student.prototype = Person.prototype;

  Student.prototype.gradeCheck = function() {
    return `name: ${this.name} age: ${this.age} grade: ${this.grade}`;
}

  let human = new Person('james', 33);
  let james = new Student('james', 18, 'D');
  console.log(james.gradeCheck());  // name: james age: 18 grade: D;
  console.log(james.information());  // name: james age: 18;
  console.log(human.gradeCheck());  // name: james age: 33 grade: undefined;

Student.prototype = Person.prototype; 이 코드만 넣었는데 human.gradecheck()가 실행이 가능해졌습니다.

일단 간단하게 그림으로 표현을 해보겠습니다.

서로 같은곳을 참조하고 있어 어떤기능을 추가할때마다 두개클레스 모두 기능이 추가되는 불편이 있을겁니다.

다시 이를 해결하기 위해서 Object.create() 메소드를 써서 코드를 짜보겠습니다.

function Person(name, age) {
    this.name = name;
    this.age = age;
  }
  
  Person.prototype.information = function() {
    console.log(`name: ${this.name} age: ${this.age}`);
  } 

  function Student(name,age, grade) {
      Person.call(this,name,age);
      this.grade = grade;
  }


  Student.prototype = Object.create(Person.prototype);
  Student.prototype.constructor = Student;

  Student.prototype.gradeCheck = function() {
    return `name: ${this.name} age: ${this.age} grade: ${this.grade}`;
}

  let human = new Person('james', 33);
  let james = new Student('james', 18, 'D');
  console.log(james.gradeCheck()); // name: james age: 18 grade: D
  console.log(james.information()); // name: james age: 18
  console.log(human.information());  // name: james age: 33
  console.log(human.gradeCheck()); // Error 발생

Object.create() 메소드에 파라메타값으로 Person.prototype를 추가하니 서로 참조하는게 아니라 Studenet.prototypePerson.prototype을 상속을 받게 되었고, Student.prototype.constructor = Student;를 코드를 추가해 Student.prototype.constructor Person을 바라보고 있는걸 Student로 변경을 해주었습니다.

constructor은 인스턴스가 초기화 될때 실행하는 생성자함수(인스턴스의 초기값을 셋팅);

prototype으로 상속받는 방식은 번거러워 ES6 Class 문법을 사용하여 상속 받는 방식을 사용하면 유용하다고들 합니다.
다음 주제는 ES6 Class 문법으로 상속을 해보도록 해보겠습니다.


간단요약
prototype 상속패턴

Object.create()을 사용하여 상속

1.Student(자식클래스).prototype = Object.create(Person.prototype(부모클래스))

2.Student.prototype.constructor = Student사용하여 constructor를 다시 원복실시.

3.주의점은 자식클래스가 부모클래스 프로토타입을 상속받은 후 자식클래스의 프로토타입을 생성할것! 상속받기전에 자식클래스의 기능을 추가한다면 다 지워짐 ㅠㅠ

ex) 1. good example

Student.prototype = Object.create(Person.prototype);
Student.prototype.constructor = Student;

Student.prototype.gradeCheck = function() {
    return `name: ${this.name} age: ${this.age} grade: ${this.grade}`;
  1. bad example
  Student.prototype.gradeCheck = function() {
    return `name: ${this.name} age: ${this.age} grade: ${this.grade}`;

Student.prototype = Object.create(Person.prototype);
Student.prototype.constructor = Student;

let james = new Student('james', 18, 'D');
console.log(james.gradeCheck()); // Error발생 기존메소드는 삭제
profile
기록의 중요성

0개의 댓글