728x90
728x90

JS는 프로토타입 기반 언어라서 상속 개념이 없지만 클래스와 비슷하게 흉내내는 여러 기법들이 있으며 ES6부터는 클래스 문법이 추가되었습니다. 여기서도 일정 부분 프로토타입을 활용하고 있기 떄문에 ES5에서 클래스를 흉내내기 위해서도 구현 방법을 학습해두면 개발에 도움이 됩니다. 그렇다면 클래스와 인스턴스의 개념부터 잡아봅시다. 

 

 

 

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


객체지향 플그래밍에서 항상 등장하는 1요소인 클래스의 사전적 의미는 계급, 집단, 집합 등으로 번역합니다.

음식 - 과일 - 사과, 배, 바나나, 귤 등을 예시로 들 때 각 과일들은 실존하는 사물에 해당되나 '음식'이나 '과일'은 사과, 배 등의 공통 속성을 모아 정의한 것일 뿐 추상적인 개념입니다. 과일은 음식과의 관계에서 하위 개념입니다. (superClass - subClass) 
귤류 - 감귤, 오렌지, 자몽, 천혜향, 레몬 등 클래스는 하위로 갈 수록 속성을 상속하면서 더 구체적 요건이 추가 또는 변경됩니다. 구체화되어도 추상적인 점은 여전합니다.

반면 클래스의 속성을 지니는 실존하는 개체들은 인스턴스라고 합니다. 사전적 의미는 사례라고 하며, 풀어서 어떤 조건에 부합하는 구체적인 예시 정도가 되겠습니다. 조건은 클래스를 의미하며 어떤 클래스에 속한 개체는 그 클래스의 조건을 모두 만족하므로 그 클래스의 구체적인 예시, 인스턴스가 됩니다.

현실에서는 한 개체가 같은 레벨에 있는 서로 다른 여러 클래스의 인스턴스일 수 있으며 (여성, 노동자, 한국인, 블로거) 각 분류는 서로 밀접한 관련이 없는 별개의 분류체계입니다. 이미 존재하는 나를 성질에 따라 분류하면서 클래스가 생성되지만, 반대로 플그래밍 언어상에서는 사용자가 직접 클래스를 정의하며, 클래스를 바탕으로 인스턴스를 만들 때 개체가 클래스의 속성을 가지게 됩니다.

또한 한 인스턴스는 하나의 클래스만을 바탕으로 만들어지며 어떤 인스턴스가 다양한 클래스에 속할 수 있지만 클래스들은 인스턴스 입장에서 직계존속입니다. 다중상속의 여부를 떠나 결국 인스턴스를 생성할 때 호출할 수 있는 클래스는 오직 하나뿐이기 때문입니다. 마지막으로 현실의 클래스와 다른점은 사용하기에 따라 추상적인 대상일 수도 있고 구체적인 개체가 될 수 있다는 것입니다.

 

 

 

02 자바스크립트의 클래스


 

생성자 함수 Array를 new 연산자와 함께 호출하면 인스턴스가 생성됩니다. 이 때 Array를 일종의 클래스라고 하면 Array의 prototype 인 객체 내부 요소들이 프로토타입 체이닝에 의한 참조에 의해 인스턴스에 상속되는것과 비슷합니다. (내부 프로퍼티 중 prototype 프로퍼티를 제외한 나머지는 인스턴스에 상속되지 않습니다.)

인스턴스에 상속되는지 (인스턴스가 참조하는지) 여부에 따라 스태틱 멤버, 인스턴스 멤버로 나뉩니다.

[ ... ] 추가 예정

 

 

 

03 클래스 상속


7-3-1 기본 구현

 

이 단원은 그간 고군분투의 역사 정리 정도의 단원입니다. 

프로토타입 체이닝을 활용해 클래스 상속을 구현하고 최대한 객체지향언어의 전통적인 클래스와 비슷한 형태까지 발전시켜 보겠습니다.
6-2-4 절의 다중 프로토타입 체인 예시는 사실 클래스 상속의 핵심이라서 다시 살펴보겠습니다. 

 

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.dir(Grade);

 

 

7-6 클래스 상속과 프로토타입 체인의 관계

 

위 예시는 세부적으로 superClass와 subClass가 완벽히 구현된 것은 아니며 문제점 두가지가 있습니다.

1)  length 프로퍼티가 삭제 가능(configurable)
2) Grade.prototype에 빈 배열을 참조

 

 

문제점 중 우선 length부터 다뤄보겠습니다. Array 내장 클래스를 상속하는 Grade 클래스 예제입니다.

 

7-3 length 프로퍼티를 삭제한 경우

 

 

 

 

 

 

 

 

length 프로퍼티를 삭제하고 push를 했습니다. push한 값이 0번째 인덱스에 들어갔고 length가 3에서 1이 되었습니다. 
내장객체가 배열 인스턴스length 프로퍼티는 configurable 속성이 false라서 삭제가 불가하지만,
Grade 클래스의 인스턴스는 배열 메서드를 상속하지만 기본적으로는 일반 객체의 성질을 그대로 지니므로 삭제가 가능해서 문제가 생깁니다.

 

Grade(3) [100, 80, 90]
Grade [70, 1: 80, 2: 90]

 

 

push를 했을 때 0번째 인덱스에 70이 들어가고 length가 1이 될 수 있었던 이유는
Grade.prototype ( g.__proto__ )이 빈 배열이 가리키고 있기 때문입니다. 
빈 배열의 length가 0 -> 값 할당, length 1만큼 증가라는 명령이 문제 없이 동작했습니다.

push 명령에 의해 JS 엔진이 g.length를 읽고자 하는데 g.length가 없음 -> 
프로토타입 체이닝을 탐 -> g.__proto__.length 읽음

 

 

* Grade.prototype에 요소를 포함하는 배열을 매칭한다면

 

 

 

 

 

 

 

Grade(3) [100, 80, 90]
Grade(5) [100, 80, 90, empty, 70]

 

push 명령에 의해 JS 엔진이 g.length를 읽고자 하는데 g.length가 없음 -> g.__proto__.length 읽음
값이 4 -> 인덱스 4에 70을 넣음 ->  g.length에 5를 부여

클래스에 있는 값이 인스턴스의 동작에 영향을 준다는 것은 클래스의 추상성을 해치는 것입니다.  클래스가 인스턴스와의 관계에서는 구체적인 데이터를 가지지 않고 인스턴스가 사용할 메서드만을 가지는 추상적인 틀로서만 작용해야 합니다. 그렇지 않는다면 언젠가 예기치 않은 오류를 맞이합니다. (클래스가 구체적인 데이터를 지니지 않기 위한 방법은 다음 절 참조)

 

다음 예제로는 사용자가 정의한 두 클래스 사이에서의 상속관계를 구현해보겠습니다.
직사각형 클래스와 정사각형 클래스를 만들어 보겠습니다.
각 클래스에는 넓이를 구하는 getArea라는 메서드를 추가했습니다.

 

7-5 Rectangle, Square class

 

 

 

 

 

 

width 프로퍼티가 공통이고 getArea는 다른 부분이 있으나 비슷합니다.
Square에서 height 프로퍼티에 width 값을 부여하는 형태가 된다면 getArea도 동일하게 바꿀 수 있습니다

 

7-6 Rectangle, Square class trans

 

 

 

 

 

 

Square를 Rectangle의 하위 클래스로 넣어도 될 것 같고
getArea 메서드는 동일한 동작을 하니 상위 클래스에서 정의하고 하위클래스에서는 메서드 상속하면서
height 대신 width를 넣어줄 수 있습니다.

 

7-7 Rectangle을 상속하는 Square class

 

 

 

 

 

첫 줄에서 Square의 인스턴스임을 표시하고 있고 width와 height에 5가 잘 들어있습니다. __proto__는 Rectangle의 인스턴스임을 표시하고 이어서 width, height에 모두 undefined가 할당되어 있습니다. Square.prototype에 값이 존재하여 이후에 임의로 Square.prototype.width (height)에 값을 부여하고 sq.width(height)의 값을 지워버린다면 프로토타입 체이닝에 의해 엉뚱한 결과가 나오는 문제가 생길 수 있습니다.

Square 생성자 함수 내부에서 Rectangle의 생성자 함수를 호출해 인자 height의 자리에 width를 전달했고
메서드를 상속하기 위해 Square의 프로토타입 객체에 Rectangle의 인스턴스를 부여했습니다. 
-> 작동은 하나 클래스에 있는 값이 인스턴스에 영향을 줄 수 있어 완벽한 클래스 체계라 볼 수 없습니다.

 

console.dir(sq);

 

 

7-8  Rectangle -> Square 상속 관계 구현 (1) - 도식

 

 

constructor가 여전히 Rectangle을 바라보고 있는 문제도 있습니다. sq.constructor로 접근하면 프로토타입 체이닝을 따라 sq.__proto__.__proto__, 즉 Rectangle.prototype에서 찾게 되며 이는 Rectangle을 가리키고 있기 때문입니다.

 

var rect2 = new sq.constructor(2, 3);
console.log(rect2); // Rectangle {width: 2, height: 3}

 

이처럼 하위 클래스로 삼을 생성자 함수의 prototype 에 상위 클래스의 인스턴스를 부여하는 것만으로도 기본적 메서드 상속은 가능하지만 다양한 문제가 발생할 여지가 있어 구조적 안정성이 떨어지므로 다음 단원에서 이 문제들을 해결하겠습니다.

 

 

 

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

 

클래스 (prototype)가 구체적인 데이터를 지니지 않게 하는 방법 중 가장 쉬운 것은 만든 후 프로퍼티들을 일일히 지우고 새로운 프로퍼티를 추가할 수 없게 하는 것입니다.

 

delete Square.prototype.width;
delete Square.prototype.height;
Object.freeze(Square.prototype);

 

프로퍼티가 많다면 반복작업이 이루어지니 반복을 없애고 범용적으로 동작을 수행하는 함수를 만들어봅시다.

 

7-8 클래스 상속 및 추상화 방법(1) - 인스턴스 생성 후 프로퍼티 제거

 

 

 

 

extendClass1 함수는 SuperClass와 SubClass, SubClass에 추가될 메서드들이 정의된 객체를 받아서 [...]

 


 

 

코어자바스크립트 요약 - 01.데이터타입

스터디 발표 정리 (1) - 코어자바스크립트 01.데이터타입 01 데이터타입의 종류 기본형 / 참조형 데이터타입의 차이는 기본형은 할당이나 연산 시 복제되고 참조형은 참조되는 것 그리고 기본형은 불변성을 띈다는..

coding-restaurant.tistory.com

 

 

코어자바스크립트 요약 - 02.실행 컨텍스트

01 실행 컨텍스트 execution context 실행컨텍스트는 자스에서 중요한 개념 중에 하나이며 클로저를 지원하는 언어에서 유사한 개념이 적용되어 있다. 실행컨텍스트란 실행할 코드에 제공할 환경 정보들을 모아놓..

coding-restaurant.tistory.com

 

 

코어자바스크립트 요약 - 03. this

상황별로 this가 어떻게 달라지는지, 왜 그런지, 예상과 다른 대상을 가르킬 경우 원인을 효과적으로 추적하는 방법을 정리했다. 다른언어와 자바스크립트 this 의 차이점 대부분 객체지향언어의 this : 클래스로..

coding-restaurant.tistory.com

 

 

코어자바스크립트 요약 - 04. 콜백 함수

01 콜백 함수 callback function 요약 : 다른 코드의 인자로 넘겨주는 함수. 필요에 따라 넘겨받은 후 적절한 시점에 시행되며 제어권과 연관이 있다 어떤 이벤트가 발생한 후, 수행될 함수를 의미 다른 코드 (함..

coding-restaurant.tistory.com

 

 

코어자바스크립트 요약 - 05. 클로저

01 클로저의 의미 및 원리 이해 클로저 closure : 여러 함수형 프로그래밍 언어에서 등장하는 보편적인 특성으로 자바스크립트 고유의 개념이 아니라서 ECMAScript 명세에서도 정의를 다루지 않고 있고 문헌마다..

coding-restaurant.tistory.com

 

 

코어자바스크립트 요약 - 06. 클로저

6-1-2 constructor 프로퍼티 생성자 함수의 프로퍼티인 prototype 객체 내부에 있는 프로퍼티, constructor 프로퍼티 constuctor 프로퍼티는 생성자 함수, 즉 자기 자신을 참조하는 프로퍼티입니다. 인스턴스와의..

coding-restaurant.tistory.com

 

728x90
728x90
블로그 이미지

coding-restaurant

코딩 맛집에 방문해주셔서 감사합니다.

,

v