관리 메뉴

Jerry

One Paper: Inheritance Pattern 본문

Front/JavaScript

One Paper: Inheritance Pattern

juicyjerry 2020. 11. 7. 01:10
반응형
#1과 #2, 두 부분으로 나누어 정리해보았습니다. 
#1을 MDN의 내용을 참조하였고, #2는 코드스테이츠 자료를 참조하였습니다. 

#1

Inheritance in JavaScript

 

Inheritance in JavaScript

This article has covered the remainder of the core OOJS theory and syntax that we think you should know now. At this point you should understand JavaScript object and OOP basics, prototypes and prototypal inheritance, how to create classes (constructors) a

developer.mozilla.org

이번 상속 패턴의 내용은 MDN을 보고 일정 부분을 번역해보았습니다.

자세한 내용은 위 링크를 통해 확인하시길 바랍니다.


지금부터 OOJS(Object-oriented JavaScript)에 대한 상세한 설명과 함께,  이 글은 부모 클래스에서 특징들을 상속받은 자식 클래스가 어떻게 생성되었는지 보여준다. 추가로, OOJS를 어디서 언제 사용해야 되는지를 볼 것이며, 최신 ECMA 스크립트 문법에서 어떻게 다뤄지는지 같이 볼 것이다.

 

시작에 앞서

먼저, 밑에 나오는 코드들을 이용하여 Person( ) 생성자를 만들어 보자.

function Person(first, last, age, gender, interests) {
  this.name = {
    first,
    last
  };
  this.age = age;
  this.gender = gender;
  this.interests = interests;
};

 

다음으로, 메서드들은 모두 생성자 프로토타입에 정의한다.

Person.prototype.greeting = function() {
  alert('Hi! I\'m ' + this.name.first + '.');
};

다음으로, 

우리가 Person 생성자를 만든 것처럼, Teacher 클래스를 생성하고 추가로, 새로운 속성인 subject와 greeting 메서드를 추가해보자.

 

그렇다면, Teacher( ) 생성자를 먼저 만들어 보자. 

function Teacher(first, last, age, gender, interests, subject) {
  Person.call(this, first, last, age, gender, interests);
  
  this.subject = subject;
}

이 코드 형식은 앞서 만들어본 Person 생성자 코드와 비슷하지만, 다른 점이 생겼다!

그것은 바로 call 메서드다. 

 

call 메서드는 기본적으로 현재 위치에서 다른 곳에 있는 함수를 호출할 수 있게 해 준다. 

첫 번째 자리에 매개변수는 함수가 실행할 때 this값을 지정하며, 다른 매개변수들은 함수가 호출될 때 함수로 전달되어야 하는 것들을 지정해야 한다.

 

우리는 Teacher( ) 생성자를 Person( ) 생성자로부터 같은 매개변수들을 설정하기 위해서 우리는 call( ) 메서드를 호출해야 한다.

function Teacher(first, last, age, gender, interests, subject) {
  this.name = {
    first,
    last
  };
  this.age = age;
  this.gender = gender;
  this.interests = interests;
  this.subject = subject;
}

간단하게 위 코드를 짜보았는데 위 코드는 Person 생성자 상속과 관련이 없고 단지 새로 재정의 한 것뿐이다.  

그렇다면, 상속받기 위해서는 어떻게 해야 될까?

 

만약, 매개변수가 없는 생성자를 상속받을 경우에는 추가로 인수를 call 메서드를 이용하여 지정할 필요가 없다. 밑에 코드처럼 간단하게 할 수 있다.

function Brick() {
  this.width = 10;
  this.height = 20;
}

밑에 코드처럼, 다른 함수의 매개변수를 불러오고 싶으면 이렇게 할 수 있다.

function BlueGlassBrick() {
  Brick.call(this);
  
  this.opacity = 0.5;
  this.color = 'blue';
}

call 메서드에서 this 키워드만 지정해준 이유는 부모 매개변수의 속성 중에서 상속받은 것이 없기 때문에 다른 파라미터는 없게 되었다.


Teacher() 프로토타입 설정과 생성자 참조 설정하기

 

지금까지 별문제 없이 여기까지 왔다. 하지만, 한 가지 문제가 있다. 우리는 새로운 생성자를 정의하였고 이 생성자는 기본값으로 스스로를 참조를 하는 객체를 가진 프로토타입 속성을 지닌다. 이것은 Person 생성자의 프로토타입 속성이 포함되지 않았다.

참고로, Object.getOwnPropertyNames(Teacher.prototype) 구문을 이용하여 Teacher과 Person이 프로토타입 속성을 가지고 있는지 여부를 알 수 있다.

 

우리가 Teacher()에서 Person( )의 프로토타입을 상속받고 싶다면 어떻게 해야 할까?


  1. 이전 추가사항 밑에 아래의 코드를 추가한다.

Teacher.prototype = Object.create(Person.prototype);

 여기서 나온 새로운 친구 create( ) 메서드는 새로운 객체를 생성하기 위함과 Teacher.prototype을 생성하기 위해서 사용되었다. 또한, Person.prototype를 상속받았기에, 필요하다면 Person.prototype을 이용할 수 있다. 

 

 

  2.  1번 과정 다음으로 넘어가기 전에 우리는 해야 될 것이 하나 더 있다. 

현재, Teacher.prototype의 생성자 속성은 Person ( )와 같다. 그 이유는 좀 전에 우리가 Teacher.prototype에서 Person.prototype의 속성을 상속받았기 때문이다. (콘솔에 코드를 찍어보면 알 수 있다 - Teacher.prototype.constructor)

 

  3.  현재 상황은 문제가 될 수 있기 때문에, 문제가 없도록 바르게 수정해야 할 필요가 있다. 그러기 위해선, 아래의 소스코드를 너의 소스코드 하단부에 추가해보자.

Object.defineProperty(Teacher.prototype, 'constructor', { 
    value: Teacher, 
    enumerable: false, // so that it does not appear in 'for in' loop
    writable: true });

  4. 파일을 저장하고 브라우저의 리프레쉬(새로고침) 한 후,  Teacher.prototype.constructor를 입력하면, Teacher( )를 리턴할 것이다. 결론적으로, 우리는 Person( )으로부터 상속에 성공하였다!

 

 

출처: MDN


#2 __proto__, constructor, prototype이 각각 어떤 관계를 가지고 있는가요?

#3 Object.create 메서드는 무엇인가요?

#4

ES6 class 키워드 및 super 키워드 어떻게 사용할까요?

 

#2와 #3의 질문에 대한 답이 아래 내용 안에 있으니 유념하여 보면 이해가 더 될 것이다.

 

제목: Subclassing  부제목:  Understanding Prototype Chain

 

constructor는 우리말로 생성자라고 부르며, 특정 객체가 생성될 때 사용한다. 즉, 인스턴스가 초기화될 때 실행하는 생성자 함수

prototype(__proto__)은 우리말로 원형(또는 원형 객체)라고 하며, 모델의 청사진을 만들 때 쓰는 원형 객체( original form) d

this는 함수가 실행될 때, 해당 scope마다 생성되는 고유한 실행 context (execution context) new 키워드로 인스턴스를 생성했을 때는 해당 인스턴스가 바로 this의 값이 됨 (#2)

 

 

좌: 새로운 객체를 생성자로 생성할 때를 도식화함

우: prototype chain : 객체에 있는 __proto__끼리 연결되어 있음


Q. 지금까지 내용을 바탕으로 다음에 밑에 나오는 코드가 되게 하려면 어떻게 해야 할까? 

steve instanceof Human === true;
john instanceof Student === true;
john instanceof Human === true;

문서에 사용하지말라고 되어있어서, 참고용으로만 사용하도록 하자

 

객체 참조가 바뀌어 student.prototype과 Human.prototype이 같아진다. => learn이 Human에도 생기게 된다.

 

 

완전히 동일한 기능을 가진(복사한) 객체를 만든다. ( =카피한다 )

 

 

카피가 Student를 바라보지 않고 Human을 바라고 보고 있다. constructor를 Student를 바라보게 만들어줘야 한다. (상속 연결)

 

 

Human의 this가 undefined 된다.  Human의 context가 전달이 안 되기 때문에 call 메서드를 사용해줘야 한다.

 

여기까지 지저분(?)함을 해결해주려고 나온 것이 ES6의 class keyword이다!

비록 지저분하지만, 프로토타입 본질 혹은 프로토타입을 제대로 이해할 수 있는 효과를 얻을 수 있다.

 

 

 

 

 

출처: 코드스테이츠 강의 자료

반응형

'Front > JavaScript' 카테고리의 다른 글

async 예외처리(의 까다로운점?)  (0) 2021.04.15
자바스크립트 원시값?  (1) 2021.04.14
async await 이란?  (0) 2021.04.14
One Paper: Understanding Prototype  (0) 2020.11.07
One Paper: Object Oriented Programming  (0) 2020.11.01