본문 바로가기
프로그래밍/JavaScript

자바스크립트 클래스

by 물고기고기 2021. 8. 8.

클래스란?

클래스란 특정 집단을 묶기 위해 추상화 한 개념, 이 안에 속하는 것들을 인스턴스라고 함

프로그래밍에서 인스턴스에서 클래스들은 직계존속. 인스턴스를 생성할 때 호출할 수 있는 클래스는 오직 하나이기 때문.

자바스크립트의 클래스

인스턴스에 상속되는지에 따라

  • 스태틱 멤버
  • 인스턴스 멤버

로 구분됨

자바스크립트에서는 인스턴스에서도 직접 메서드를 정의할 수 있음. 그래서 인스턴스 메소드보단

프로토타입 메서드라고 부름

 

// 생성자
var Rectangle = function (width, height) {
  this.width = width;
  this.height = height;
};

// prototype method
Rectangle.prototype.getArea = function () {
  return this.width * this.height;
};

// static method
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
console.log(rect1.isRectangle(rect1));  // error
console.log(Rectangle.isRectangle(rect1));  // true

rect1 3,4를 할당. 프로토타입 객체에 할당한 메서드는 인스턴스가 마치 자신의 것 마냥 호출할 수 있으니까 그 다음 rect1.getAreat는 프로토타입 객체에 할당된 getAreat를 호출한 셈이니 결과값이 제대로 반환됨. 이것은 인스턴스에서 직접 프로토타입 메서드를 호출한 경우임

그 다음엔 rect1 인스턴스에서 isRectangle이라는 메서드에 접근하는 경우인데. rect1에 해당 메서드(isRectangle)가 있는지 검색했는데 없고. rect1의 프로토타입에도 없으므로 결국 에러가 남.

이렇게 인스턴스에서 직접 접근할 수 없는 메서드를 스태틱 메서드라고 함.(둘다 메서드니까)

이 경우 바로 아래처럼 rect1의 부모 생성한테 접근해야 원기능 사용이 가능함.

 

클래스 상속

ES6에서는 다른 방법이 존재한다니까 읽고 넘기면 됨

 

프로토 타입 체인을 활용

// 프로토타입 체이닝
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 = []; // Grade의 기본 타입을 array로 변경하는 것.

var g = new Grade(100,80);

프로토 타입 체이닝을 이용해 클래스 상속을 구현 함

Array.prototype.slice.call(arguments)란 이 코드가 존재하는 함수의 매개변수로 넘어온 값들을 유사배열객체로 변환하겠다는 뜻

 

그래서 문제점은?

g.push(80);
console.log(g); //Array { '0': 100, '1': 80, '2': 80, length: 3 }

delete g.length;
g.push(90);
console.log(g); //Array { '0': 90, '1': 80, '2': 80, length: 1 }

내장객체인 배열 인스턴스의 length는 configurable(삭제 가능)속성이 false라서 삭제가 불가능.

그러나 Grade클래스의 인스턴스는 배열 메서드를 상속하나 일반 객체의 성질을 지니므로 삭제가 됨.

근데 왜 100이 없어진걸까?

Grade.prototype이 빈 배열을 가리키고 있기 때문. 빈배열의 length가 0이므로 여기에 값을 할당하고 length는 1만큼 증가시키라는 명령.

 

그런데 length가 Grade.prototype에 포함하는 경우라면?

Grade.prototype에 요소를 포함하는 배열을 매칭시켰다면?

Grade.prototype = ['a','b','c','d']; // Grade의 기본 타입을 array로 변경하는 것.

var g = new Grade(100,80);

g.push(90);
console.log(g); //Array { '0': 100, '1': 80, '2': 90, length: 3 }

delete g.length;
console.log(g); //Array { '0': 100, '1': 80, '2': 90 }

g.push(70); 
console.log(g); //Array { '0': 100, '1': 80, '2': 90, '4': 70, length: 5 }

이거는 g.push(70)에서 length가 없으니까 prototype에서 length(4)를 찾아서 가져오는 것

 

 

 

그 뒤에것들을 공부를 못했음

ES6에서의 클래스 상속

여기서는 ES5 체계에서의 생성자 함수 및 프로토타입과 ES6의 클래스 문법을 비교.

ES5

var ES5 = function(name){
        	this.name = name;
        };
        ES5.staticMethod = function(){
        	return this.name + ' staticMethod';
        };
        ES5.prototype.method = function(){
        	return this.name + ' method';
        }
        var es5Instance = new ES5('es5');
        console.log(ES5.staticMethod());	//ES5 staticMethod
        console.log(es5Instance.method());	//es5 method

ES6

var ES6 = class{
        	constructor (name){
        		this.name = name;
        	}
        	static staticMethod(){
        		return this.name + ' staticMethod';
        	}
        	method = function(){
        	return this.name + ' method';
        	}
        }

        var es6Instance = new ES6('es6');
        console.log(ES6.staticMethod());	//ES6 staticMethod
        console.log(es6Instance.method());	//es6 method

class라는 명령어 뒤에 바로 {} 가 등장 , 중괄호 묶음 내부가 클래스 본문 영역

constructor 이름 뒤에 ()가 등장, 클래스 본문에서는 function 키워드를 생략하더라도 모두 메서드로 인식. 이 부분이 생성자 함수와 동일한 역할 수행.

static 메소드(es6 객체만 쓸 수 있는것) 따로 선언

그리고 method가 등장했는데 이는 자동으로 prototype객체 내부에 할당되는 메서드. 인스턴스가 프로토타입 체이닝을 통해 호출 가능한 메서드.

 

요약

ES5의 생성자함수 => ES6의 class내에서 constructor

ES5의 메서드 => ES6의 static 메서드

ES5의 prototype.메서드 => ES6의 프로토타입 메서드

 

클래스 상속(ES6)

ES5에는 존재X, ES6에서만 존재.

 

var Rectangle = class{
  constructor(width, height){
    this.width = width;
    this.height = height;
  }
  getArea(){
    return this.width * this.height;
  }
};

var Square = class extends Rectangle{
  constructor(width){
    super(width,width);
  }
  getArea(){
    console.log('size is:',super.getArea());
  }
};

Square를 Rectangle 클래스를 상속받는 SubClass로 만들기 위해 class 명령어 뒤에 extends라고 추가.

 

let square = new Square(10);
square.getArea(); //size is: 100

 

댓글