본문 바로가기

프로그래밍/JavaScript(JS)

자바스크립트(JavaScript) - 상속

상속은 기존에 있던 프로퍼티와 메소드를 자식이 되는 객체에게 물려주는 것입니다.

자바스크립트에서 객체에 상속을 해야 한다면 프로토타입을 사용해서 프로퍼티와 메소드를 상속하기도 합니다.

프로토타입을 이용해서 상속을 하는 것이 아닌 객체 상속을 알아보도록 하겠습니다.

 

객체 상속

객체에 있는 프로퍼티와 메소드를 다른 객체에 상속시키려면 call(), apply() 메소드를 사용하여 상속을 시킬 수 있습니다.

function a(name, list) { 
    this.name = name;
    this.show = function() {
    	console.log(name);
    };
}

a.prototype.ab = function () {
    console.log(this.name);
};

function b() {
  a.call(this,"abc","test");
  this.bb = "bb";
}

var c = new b();
console.log(c); // -> b {name: 'abc', show: ƒ, bb: 'bb'}

 

생성자 함수에서 사용될 this 값과 사용할 인수를 적어주고 call() 메소드를 호출하게 되면 최종적으로 인스턴스 c객체에 a에 있던 name, show가 추가됩니다.

 

따라서 인스턴스 객체인 c를 출력해보면 a에 있던 프로퍼티들이 상속이 된 것을 볼 수 있습니다.

 

어째서 call 메소드로 호출했는데 인스턴스 객체에 프로퍼티가 추가가 되는 것인가?

ES6기준으로 설명하겠습니다.

 

new b() 코드가 실행되면 new 키워드의 평가가 이루어집니다. 내부 과정에서 생성자 함수 b에 대한 [[Construct]] 가 호출이 됩니다. 이 과정에서 새로운 하나의 빈 객체가 생성되고 FunctionEnvironmentRecords가 생성되며 만들어진 빈 객체가 this를 설정하는 과정에서 this 객체로 설정이 되게 됩니다. 그 후 b 함수 내용이 실행이 되어 평가가 시작됩니다.

 

b함수가 실행이 되면 a.call() 메소드가 호출이 시작되며 이전 Execution Context는 일시 중지하고 됩니다. 여기서 this는 현재 실행되어있는 Execution Context에 있는 Environment에 this로 설정된 값입니다. 따라서 아까 new가 실행될 때 만들어진 비어있는 객체가 되겠습니다. this와 인수가 넘어가 a가 call() 메소드로 호출되면 새로운 Execution Context를 만들며 FunctionEnvironmentRecords를 만들고 Environment에 this값을 설정하게 됩니다. 즉 둘 다 같은 객체입니다.

 

그 후 a함수 내용이 평가가 되면서 this.name, this.show코드가 실행이 될때 this의 값을 가져와 값을 만들어 저장하게 됩니다. a의 내용이 끝나고 다시 돌아와 일시 정지되었던 Execution Context를 다시 실행 상태로 변경한 뒤 나머지 작업을 진행합니다. 모든 작업이 끝나면 만들어진 객체를 리턴합니다.

 

프로토타입도 상속하기

call이나 apply 메소드로 상속을 했지만 프로토타입이 빠져있어서 공유할 메소드는 상속되지 않았습니다. 계속해서 프로토타입도 상속을 해보겠습니다. 

 

방법은 간단합니다. 

첫번째로 상속받을 생성자 함수의 프로토타입을 Object.Create() 메소드로 상속하는 생성자 함수의 프로토타입으로 새로 만들어줍니다.

두 번째로 생성자 함수의 프로토타입의 생성자 프로퍼티를 생성자 함수로 변경해주면 끝이 납니다.

function a(name, list) { 
    this.name = name;
    this.show = function() {
    	console.log(name);
    }
};

a.prototype.ab = function () {
	console.log(this.name);
};

function b()
{
  a.call(this,"abc","test");
  this.bb = "bb";
}

b.prototype = Object.create(a.prototype);
b.prototype.constructor = b;

var c = new b();
console.log(c);

프로토 타입을 create 메소드로 a의 프로토타입으로 생성해주고 b생성자 함수와 프로토타입의 연결이 끊기지 않게 b생성자 함수의 프로토타입 객체에 있는 생성자도 변경을 하면 끝이 납니다. 

 

클래스 상속

https://bearcomputer.tistory.com/34

 

상속을 하는 이유는?

코드를 쓰다 보면은 재사용되는 코드들이 많이 있습니다. 그중에 새로운 객체를 만들 때 중복되는 프로퍼티와 메소드를 재사용해서 좀 더 확장한 객체를 만들 수 있고 중복된 코드를 작성하지 않아 유지보수가 높기 때문입니다.

 

참고

모던 자바스크립트 입문(이소 히로시 지음, 서재원 옮김)

https://developer.mozilla.org/ko/docs/Learn/JavaScript/Objects/Inheritance

https://262.ecma-international.org/6.0/#sec-ecmascript-function-objects-construct-argumentslist-newtarget

https://262.ecma-international.org/6.0/#sec-ecmascript-function-objects-call-thisargument-argumentslist