Thief of Wealth

총 3가지 예제를 통해서 javascript의 class를 function으로 변환해봅시다.

이게 가능한 이유는, javascript class는 그저 syntactic sugar이기 때문이고, 내부적으로는 function과 prototype의 조합으로 이루어져 있기 떄문입니다.

 

예제 1.

class A {
	constructor(x,y) {
    	this.x = x;
        this.y = y;
    }
}

이것은 function으로 다음과 같이 바꿀 수 있습니다.

 

function A(x,y) {
	this.x=x;
    this.y=y;
}

간단합니다!

 

그럼 메서드를 추가해봅시다.

예제2.

class A {
	constructor(x,y){
    	this.x = x;
        this.y = y;
    }
    
    say(){
    	return "say";
    }
    
    speak: () => {
    	return "speak";
    }
    
    
}

메서드로 일반 function과 arrow function이 있습니다.

이것은 어떻게 변환될까요?

 

function A (x,y) {
	this.x = x;
    this.y = y;
    this.speak = () => {
    	return "speak";
    }
}

A.prototype.say = function(){
	return "say";
}

일반 function 메서드는 prototype으로 들어갔고, arrow fucntion 메서드는 생성자로직과 함께 쓰이는것으로 변환됩니다.

그래서 class에서 arrow function을 메서드로 사용하는 것은 성능면이나 상속 시 오버라이딩할때의 문제가 있어서 지양되는 것 같습니다.

 

그럼 이제 상속을 추가해보겠습니다.

예제3.

class B extends A {
	constructor(x,y){
    	super(x,y);
    }
}

A는 예제2에 있던 것과 동일하게 취급하겠습니다.

 

위 코드를 function으로 변환하면 어떻게 될까요?

function B (x,y){
	A.call(this, x, y);
}

// 1
B.prototype = new A();

// 2
B.prototype = Object.create(A.prototype);
B.prototype.constructor = A;

위와 같이 됩니다. super는 상위 함수의 call로 대신할 수 있고,

1또는 2의 방법으로 B의 prototype을 A의 prototype으로 바꿔주면서, B의 prototype 생성자를 A로 바꿔주면됩니다.

new연산자를 쓰면 한번에 할 수 있습니다.

 

이제 class의 동작 방식도 알 수 있고, 위에서 잠깐 언급했던

"class에서 arrow function을 메서드로 사용하는 것은 성능면이나 상속 시 오버라이딩할때의 문제"도 예상하실 수 있을 것 같습니다.

 

풀이를 해드리면,

1. 성능

메서드가 prototype에 저장되면, 모든 인스턴스가 prototype에 정의된 함수만 사용하므로 한번만 정의하는 것인데

arrow function으로 선언되면 인스턴스가 생성될떄마다 새롭게 메서드가 생기는 꼴이다.

2. 상속시 오버라이딩 문제

1와 연관되는 문제로, 메서드를 arrow function으로 상속받았는데, 일반 function 메서드로 오버라이딩하고 있다?

그러면 상속된 메서드는 prototype이 아니라 this에 저장되어있으므로 prototype에 일반함수로 오버라이딩하려한 메서드는 호출되지도 않고 바로 this에 있는 상속받은 arrow function 메서드가 실행되게 됩니다.

그래서 메서드가 arrow fucntion으로 구현되어있으면, 상속받는 입장에서 혼란이 생길 수 있다는 뜻입니다.

 

 

profile on loading

Loading...