자바스크립트의 클래스
자바스크립트는 프로토타입 기반 언어이므로 클래스의 개념이 존재하지 않지만(ES5까지) , 하지만, 프로토타입을 클래스 관점에서 접근해보면 비슷하게 해석할 수 있어요. 즉, 프로토타입을 기반으로 클래스와 비슷하게 동작하게끔 하는 다양한 기법들이 도입돼 왔습니다.
그러다가, ES6 부터는 클래스가 도입되었습니다.
프로토타입 체이닝과 관련한 문제
console.log 의 출력값을 예측해봅시다.
var Grade = function () {
var args = Array.prototype.slice.cail(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);
delete g.length;
g.push(70);
console.log(g);
정답.
1. Grade { 0: 100, 1: 80, 2: 90, length : 3}
2. Grade { 0:70, 1:80, 2:90, length: 1 }
2번째 콘솔 값이 왜 저렇게 나오는지에 대해 궁금할 수가 있는데, 이유를 알아보겠습니다.
먼저, delete g.length 가 되는 이유가 뭘까요?
Grade 클래스의 인스턴스 (g) 는 배열 메서드를 상속하지만 기본적으로는 일반 객체의 성질을 그대로 지니므로 property 의 삭제가 가능해서, delete g.length 가 가능합니다.
delete g.length 하고 나서
g.push(70) 에서
push 명령을 할 때, 자바스크립트 엔진이 g.length 를 읽으려고 하는데, g.length 가 없으니까 프로토타입 체이닝을 타고 g.__proto__.length ( = Grade.prototype.length) 를 읽어온 것입니다. 그러면 [ ] 빈 배열의 length 가 0 이므로 여기에 값을 할당하고 length는 1만큼 증가시키라는 명령이 동작하게 되어, g[0] = 70; 이 수행되게 됩니다.
따라서, 원래 있던 [100,80,90] 에서 [70,80,90] 이 되고, length : 1 이 나옵니다.
출력 결과는 Grade { 0:70, 1:80, 2:90, length: 1 }
잘못된 방식의 코드
Grade 라는 클래스의 값을 변경했는데, 인스턴스의 값에도 영향을 주는 것은 상당히 잘못된 방식의 코드일 것입니다.
왜 ? 클래스는 구체적인 데이터를 지니지 않고, 오직 '틀' 로서만 가치가 있어야 합니다. 그렇지 않게 동작하는 것은 올바른 추상화를 한게 아닙니다.
그래서, 자바스크립트 ES5 에서는
1. 클래스가 구체적인 데이터를 지니지 않게 하는 방법
2. Super - sub 관계에서 constructor 를 sub 를 바라보도록 하기
3. 상위 클래스로의 접근 수단(super 같은) 제공
들을 통해 클래스의 추상화를 제대로 구현하기 위해 다양한 방법들을 시도했고, 이는 복잡하긴 하지만 클래스를 쓸 수는 있었습니다.
관련 내용은 코어 자바스크립트책 7-3-2 부터 참고해보시면 됩니다.
그래서 ES6 에서는 본격적으로 클래스 문법이 도입됐습니다.
클래스 문법에 대한 설명은 링크를 참고해서 실습해보시면, 클래스를 이해하시는데 도움이 될 것이라 생각됩니다. 나중에 저도 참고해서 공부해봐야 할 것같네요.
'자바 스크립트' 카테고리의 다른 글
[코어 자바스크립트 스터디] 6주차. 프로토타입 (0) | 2021.12.23 |
---|---|
[코어 자바스크립트 스터디] 5주차. 클로저 (2) | 2021.12.16 |
[코어 자바스크립트 스터디] 1주차. 데이터 타입 (0) | 2021.12.03 |