8. 클래스

gugyeoj1n·2022년 4월 28일
0

자바스크립트

목록 보기
8/9

어제 오늘 정말 역대급 근무였다. 어제 아침 8시 반에 나가서 저녁 8시 반에 오고 아침에 갑자기 5시 반에 깨워서 50분에 출발한대서 후다닥 갔더니 하루 종일 밖에 세워둠;; 뼈빠지게 일하고 국밥 한그릇 때리고 홍성에서 시위진압 훈련했다. 우리가 시위자 역할이었는데 나름 재밌었음 ㅋ ㅡ ㅋ 직기대 분들 무섭더라

아무튼 아무것도 안하고 잠만 자려다가 간신히 컴퓨터 앞에 앉았다. 오늘은 강의 마지막 내용인 클래스다

클래스 Class

클래스는 객체지향 언어에서 지겹도록 보는 문법이다. 클래스와 항상 붙어다니는 인스턴스 Instance 는 해당 클래스의 속성을 지닌 구체적인 객체를 뜻한다. 그리고 클래스 안에 클래스를 또 정의할 수 있는데, 이때 더 높은 위치에 있는, 상위 클래스에 super 를 붙이고 하위 클래스에 sub 를 붙인다.

var a = new Array();
a[0] = 1;
console.log(a);

예시로 Array 생성자 함수로 새 인스턴스를 만들고, 그 과정에서 new 연산자가 쓰인다. 여기서 Array 생성자 함수는 하나의 클래스라고 말할 수 있다. 그리고 새로 만들어진 배열 객체 a 는 인스턴스에 해당한다. 인스턴스는 구체적인 정보를 갖고, 실제 코드상에서 동작을 수행하는 역할을 한다.

Array 생성자 함수 안을 열어보면, prototype 과 그 외의 프로퍼티들이 있다. 그 중 메서드는 스태틱 메서드, 이외의 것들은 스태틱 프로퍼티라고 부른다. 이들은 Array 생성자 함수를 new 연산자 없이 함수로써 호출할 때만 의미가 있는 값들이다.

스태틱 메서드는 보통 해당 클래스로부터 만들어진 인스턴스의 개별적인 동작이 아닌, 소속 여부 확인이나 부여같은 공동체적인 판단을 필요로 하는 경우에 주로 활용된다. 한편 prototype 안에 있는 메서드들은 프로토타입 메서드라고 부른다.

클래스와 인스턴스의 관계

스태틱 값들과 프로토타입 메서드는 인스턴스가 직접 접근 가능한가로 구분한다. 프로토타입 메서드는 인스턴스와 [[Prototype]] 으로 연결되어 있어서 인스턴스에서 바로 프로토타입 메서드에 접근할 수 있다. 반면 스태틱 값들은 일반적으로 인스턴스에서 손댈 수 없다.

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

Person.getInformations = function(instance) {
	return {
    	name: instance._name,
      	age: instance._age
    };
}

Person.prototype.getName = function() {
	return this._name;
}

Person.prototype.getAge = function() {
	return this._age;
}

Person 생성자 함수와 3개의 메서드를 정의했다. Person.getInformations 는 prototype 에 속하지 않은 스태틱 메서드이다.

var human = new Person('a', 1);

console.log(human.getName());
console.log(human.getAge());
console.log(human.getInformations());

human 인스턴스를 생성하고 세 메서드를 한번씩 실행해 보면, getName 과 getAge 는 정상적으로 출력되지만 getInformations 에서 에러가 발생한다. getInformations 는 prototype 이 아닌 생성자 함수에서 접근해야 사용할 수 있기 때문이다.

console.log(Person.getInformations(human);

이렇게 작성하면 name 과 age 가 잘 출력된다.

클래스 상속

function Person(name, age) {
	this.name = name || "이름 X";
  	this.age = age || "나이 X";
}

Person.prototype.getName = function() {
	return this.name;
}

Person.prototype.getAge = function() {
	return this.age;
}

//-----------------------------------

function Employee(name, age, position) {
	this.name = name || "이름 X";
  	this.age = age || "나이 X";
  	this.position = position || "직책 X";
}

Employee.prototype.getName = function() {
	return this.name;
}

Employee.prototype.getAge = function() {
	return this.age;
}

Employee.prototype.getPosition = function() {
	return this.position;
}

이름, 나이를 담는 클래스 Person 과 이름, 나이, 직책을 담는 클래스 Employee 가 있다. 두 클래스는 다른 기능을 할 수도 있지만 겹치는 메서드가 2개나 있다. Person 클래스를 super (상위) 로, Employee 클래스를 sub (하위) 로 만들어 주면 겹치는 부분이 없어질 것이다. prototype 안에 getName 과 getAge 를 넣으면 체이닝으로 Employee 클래스의 인스턴스도 메서드를 자유롭게 사용할 수 있다.

Employee.prototype = new Person();

간단하게 Employee 의 prototype 에 Person 인스턴스를 할당해 주면 된다. 하지만 이 코드는 prototype 을 완전히 새로운 인스턴스로 바꿔 버리므로, 없어지는 기능을 다시 부여해 줘야 한다. 지금 Employee.prototype 의 constructor 속 생성자 함수는 Person 이니 이것을 Employee 로 바꿔 주도록 하겠다.

Employee.prototype.constructor = Employee;

이제 Employee 클래스는 Person 클래스의 하위 클래스가 되었다. 이제 코드를 정리하면

function Person(name, age) {
	this.name = name || "이름 X";
  	this.age = age || "나이 X";
}

Person.prototype.getName = function() {
	return this.name;
}

Person.prototype.getAge = function() {
	return this.age;
}

function Employee(name, age, position) {
	this.name = name || "이름 X";
  	this.age = age || "나이 X";
  	this.position = position || "직책 X";
}

Employee.prototype = new Person();
Employee.prototype.constructor = Employee;
Employee.prototype.getPosition = function() {
	return this.position;
}

이제 Employee 인스턴스를 생성하고 console.log() 로 안을 살펴 보면 [[Prototype]] 은 Employee 가 아닌 Person 이고, 그 안의 constructor 는 Employee 로 출력된다. 하지만 [[Prototype]] 안에 name 은 "이름 x", age 는 "나이 X" 로 저장되어 있다. prototype 에 Person 인스턴스를 할당해 줬기 때문이다. 만약 내가 Employee 인스턴스를 만들 때 한 프로퍼티라도 비운 채로 만들면 undefined 가 나와야 하는데, 프로토타입 체이닝에 의해 "이름 X" 또는 "나이 X" 가 출력되는 문제가 생긴다. 프로토타입 체이닝 상에는 프로퍼티가 아닌 메서드만을 존재하게 하는 것이 클래스의 추상적인 특징에 훨씬 부합할 것이다.

조금 복잡하지만 Employee 와 Person 사이에 다른 클래스 A 를 만들고, A 의 prototype 에 Person 의 prototype 을 연결한 채 A 의 인스턴스를 하나 생성한다. A 인스턴스 안에는 name 과 age 모두가 undefined 로 저장돼 있으니 이제 그 인스턴스를 Employee 의 prototype 으로 지정해 주면 이 문제가 해결된다.

임의로 지정한 A 클래스를 Bridge 라고 이름지어 코드를 작성해 보겠다.

function Person(name, age) {
	this.name = name || "이름 X";
  	this.age = age || "나이 X";
}

Person.prototype.getName = function() {
	return this.name;
}

Person.prototype.getAge = function() {
	return this.age;
}

function Employee(name, age, position) {
	this.name = name || "이름 X";
  	this.age = age || "나이 X";
  	this.position = position || "직책 X";
}

function Bridge() {}

Bridge.prototype = Person.prototype;

Employee.prototype = new Bridge();
Employee.prototype.constructor = Employee;
Employee.prototype.getPosition = function() {
	return this.position;
}

빈 클래스 하나를 매개체로 프로토타입 체인 상에서 불필요한 정보를 지워 주게 되었다.

꽤나 복잡한 과정으로 클래스 상속을 마쳤다. 물론 메서드 이외에 name 과 age 도 상속해 주면 더 깔끔해질 것이다.

ES6 부터는 class extends 로 매우 매우 매우 쉽게 클래스 상속이 가능하다. 하지만 강의에서 이렇게 상속 과정을 자세하게 짚어 주셔서 앞에서 배운 개념들을 상기시킬 수 있어 훨씬 유익했다. 질 좋은 강의 감사합니다 ^ㅡ^





코어 자바스크립트 강의가 끝났다. 핵심 개념들을 잘 잡고 갈 수 있었다. 이것들을 머릿속에 잘 넣어둔 채로 이제 다시 리액트 공부에 돌입해 보도록 하겠다.

근데 진짜 너무 힘들다 아니 어떻게 근무를 이렇게 빡세게 시키냐 양심도 없어? 오늘 아침밥도 버스에서 쭈구려서 김밥 먹었다고 가뜩이나 더운데 그늘도 없는 교차로에 오전 내내 세워 두고 진짜 속상하다 근데 끝나고 점심 9000원짜리 소고기국밥 줘서 기분 풀림 ㅋ ㅡ ㅋ 원래 우리 식비는 6~7000원이다.

내일은 외출, 주말 내내 시위라 한참 또 바쁘겠다 돈도 없으니 내일은 피시방에 박혀서 안 나올 예정이다

아 키보드 배송 빨리 와서 오늘 처음 써 보고 있는데, 돈값은 한다 일단 너무너무 예쁘다 초딩 취향인 나에게 알록달록 파랑 키보드는 취향저격이었다. 레오폴드랑 고민하다가 이거 샀는데 매우 만족스럽다. 근데 내가 기계식 키보드를 처음 사 봤는데, 갈축이 내가 원하던 그 무거운 찰칵찰칵 느낌이 아니어서 좀 아쉬웠다 청축은 뭐 그만큼 시끄럽다는 걸 생각해 보면 이게 제일 적당한 것 같기도 하고? 뭐가 됐든 예뻐서 좋다

그나저나 아직도 목요일이라니 실화인가 싶다 원래 바쁘면 시간이 빨리 가지 않나..? 군생활 동안 이런 억까는 존재하지 않았다 고통스럽다 고통스러우니 오마이걸 노래 들으면서 꿀잠 자러 가겠다 다들 Real Love 앨범 들으세요.. 수록곡 맛집

0개의 댓글