자바스크립트 → <프로토타입> 기반 언어 → <상속> 이라는 개념이 존재하지 않음.
ES6 에 클래스 문법 추가됨
ES5 에서 클래스를 흉내내기 위한 구현 방식을 학습하는 것은 큰 의미가 있음

01. 클래스와 인스턴스의 개념 이해

  • "음식 > 과일 > 귤 류 > 오렌지" 관계 일 때, 음식은 과일 보다 상위(superior)의 개념, 과일은 음식보다 하위(subordinate)의 개념
  • 음식은 과일의 superclass, 과일은 귤 류의 subclass, 음식은 귤 류의 super-superclass 귤 류는 음식의 sub-subclass
  • 오렌지는 클래스의 구체적인 예시, 즉 인스턴스(instance)

02. 자바스크립트의 클래스

자바스크립트는 프로토타입 기반 언어임 따라서 클래스의 개념이 존재하지 않음. 프로토타입은 일반적인 관점에서 클래스와 비슷하게 해석할 수 있다.

생성자 함수 Array를 new 연산자와 함께 호출하면(const arrayInstance = new Array()) 인스턴스가 생성된다. 이때 Array를 일종의 클래스라고 생각하면, Array의 prototype 객체 내부 요소들이 인스턴스(Instance)에 '상속'된다고 볼 수 있음.

→ 하지만 이는 상속이 아닌 <프로토타입 체이닝>에 의한 참조이다.

→ Array 내부 프로퍼티들 중 prototype 프로퍼티를 제외한 나머지는 인스턴스에 상속(참조)되지 않음

  • Array 디렉터리 구조

자바스크립트에서는 인스턴스에서도 직접 메서드를 정의할수 있기 때문에 '인스턴스 메서드'라는 명칭은 프로토타입에서 정의한 메서드를 지칭하는지 인스턴스에 정의한 메서드를 지칭하는 것인지 혼란을 야기함.

→ 자바스크립트 커뮤니티에서는 인스턴스 메서드 대신 프로토타입 메서드라고 더 많이 사용함.

  • 프로토타입에 클래스 개념을 적용
// 예제 7-1 스태틱 메서드, 프로토타입 메서드
var Rectangle = function(width, height) {
    // 생성자
    this.width = width;
    this.height = height;
}
Rectangle.prototype.getArea = function() {
    // (프로토타입) 메서드
    return this.width * this.height;
}
Rectangle.isRectangle = function(instance) {
    // 스태틱 메서드
    return instance instanceof Rectangle && instance.width > 0 && instance.height > 0
}
var rect1 = new Rectangle(3,4)
console.log(rect1.getArea());
/**
 * 답: 12
 * 해설: [프로타입 메서드] rect1.__proto__.getArea
*/ 
console.log(rect1.isRectangle(rect1)); 
/**
 * 답: Error
 * 해설: rect1 인스턴스에 메서드 없음, rec1.__proto__ 에 없음, rect1.__proto__.__proto__ (=Object.prototype) 없음
*/
console.log(rect1.Rectangle.isRectangle(rect1)); 
/**
 *  답: true
 *  해설: [static 메서드]생성자 함수를 this로 해야만 호출가능
 */

03. 클래스 상속

7-3-1 기본 구현

  • 프로토타입 체인을 활용해 클래스 상속을 구현하는게 목표
  • 코드 분석보다 예전에는 이런 방식으로 프로토타입 체인을 활용해 클래스를 구현하려고 고분고투 했구나라고 파악
// 7-2 Grade 생성자 함수 및 인스턴스
var Grade = function() {
    var args = Array.prototype.slice.call(arguments);
    for (var i = 0; i < args.length; i++) {
        this[i] = args[i];
    }
    this.length = args.length;
}
Grade.prototype = [];
var g = new Grade(100, 80) 
console.log(g) 
/**
 * 답: Object { 0: 100, 1: 80, length: 2 }
 * 해설: 
 * - 완벽한 superclass, subclass 구조가 아님 
 * - length 프로퍼티가 configurable, Grade.prototype에 빈배열을 참조시켰음
 */
// 7-3 length 프로퍼티를 삭제하는 경우
var Grade = function() {
    var args = Array.prototype.slice.call(arguments);
    for (var i = 0; i < args.length; i++) {
        this[i] = args[i];
    }
    this.length = args.length;
}
Grade.prototype = [];
var g = new Grade(100, 80) 
g.push(90);
console.log(g)
/**
 * 답: Object { 0: 100, 1: 80, 2: 90, length: 3 }
 * 해설: 의도된 출력
 */

delete g.length
g.push(70)
console.log(g)
/**
 * 답: Object { 0: 70, 1: 80, 2: 90, length: 1 }
 * 해설:
 * - 의도 되지 않은 출력
 * - g.length가 없으니 프로토타입 체이닝을 타고 g.__proto__.length를 읽어온 것
 * - 빈 배열의 length가 0, 여기에 length는 1만큼 증가 
 */

7-3-2 클래스가 구체적인 데이터를 지니지 않게 하는 방법

7-3-3 constructor 복구하기

7-3-4 상위 클래스에의 접근 수단 제공

04. ES6 클래스 및 클래스 상속

05. 정리

06. 마치며

07. 단어 설명

  • 프로토타입 언어의 특징: 객체의 원형(prototype)을 참조하여 상속과 비슷하게 구현
profile
Frontend engineer

0개의 댓글