자바스크립트 객체 지향에 관한 고찰
클래스 기반 객체 지향 프로그래밍 ⇒ 자바, 파이썬, C++
- 클래스 기반 언어에서 클래스란 객체의 상태와 기능을 정의한 설계도이다. 클래스의 인스턴스화로 생성된 객체를 인스턴스라고 한다.
- 여기서 인스턴스는 클래스에서 정의된 모든 특성에 대한 복사본(copy)이기 때문에 두 개념은 개별적이며 서로 간의 참조는 존재하지 않는다.
프로토타입 기반 객체 지향 프로그래밍 ⇒ 자바스크립트
- 프로토타입 기반 언어에서는 클래스 - 인스턴스의 개념이 아닌 오직 객체 개념만 존재한다. 다시 말하지만, ES6에 도입된 클래스 문법은 실제 클래스 패턴에 대한 모방일 뿐이다.
- 클래스 - 인스턴스의 개념이 아닌 오직 객체 개념만 존재한다는게 무슨 말이지?
- 자바에서는 Class설계도만을 작성한다 해도 Heap영역 메모리 공간을 할당하지 않는다. 후에 new연산자를 통해서 객체를 메모리 공간에 할당한다.
- 반면에 자바 스크립트에서는 리터럴 객체만을 작성한다 해도, Object생성자 함수를 통해 자동으로 메모리 공간에 할당된다. 즉 실제로 존재하는 대상을 통해 객체를 생산하게 된다는 뜻이다.
- 객체가 더 포괄적인 의미이고, 인스턴스는 어떤 클래스에서 생성 된 것인지 강조된 표현이기 때문에 엄밀히 말하면 제목과 같이 표현하는 것이 맞으나, 자바 스크립트에서도 특정 객체를 통해 만들어진 것을 표현하기 위해 인스턴스 라는 말을 많이 사용한다.
- 이것은 JS의 생성자 함수 패턴을 좀 더 클래스답게 보이기 위한 장치이며 생성된 객체는 함수의 프로토타입 객체에 연결되어 있다.
요약
- 프로토타입 ≠ 자바에서의 클래스 or 자바에서의 클래스 상속
- 프로토타입을 가장 잘 표현하는 말 ⇒ 연결
- 상속과는 다르지만, 객체는 자신의 부모 역할을 담당하는 객체와 연결되는데, 이때 부모 역할을 하는 객체를 프로토타입 이라 한다.
클래스가 아니라면, return이 없는 함수 일 때는 어떻게 객체가 생성되는 것일까?
- new 연산자가 새로운 빈 객체를 메모리 상에 생성
- 생성된 빈 객체가 this에 바인딩됨
- 바인딩된 상태에서 person함수의 내용이 실행되는데, 이 결과로 this객체의 속성이 채워진다
- person함수에 return이 없다면 만들어진 this가 return된다.
++Q. 만약 return도 없고 this도 없는 함수라면?
빈 객체로 남는다 ⇒ undefined
클래스가 아니고, 상속의 개념과도 다른데 자바 스크립트는 어떻게 객체를 설계대로 생성할 수 있을까? ⇒ __proto__ && prototype
__proto__
- 자바 스크립트의 모든 객체들은 .proto 속성을 갖는다(숨겨져 있음)
- proto ⇒ 객체와 객체를 연결하는 링크, 생성된 객체는 링크를 통해 원형을 참조한다.
- 자기 자신에게 존재하지 않는 특정 프로퍼티나 메서드를 내부 링크를 통해 상위 프로토타입으로 접근하고, 특정 프로퍼티나 메서드를 추적하는 과정을 프로토타입 체이닝 이라 한다.
객체 bar에는 c라는 속성이 없지만, proto 를 따라서 c라는 속성을 찾아낼 수 있다. 만약 d라는 속성을 찾는다면, 최상위인 Object.prototype(값으로 null을 갖고 있으며, 탐색 종료)에도 없으므로 undefined로 출력하게 된다.
prototype
- 프로토타입은 constructor 이라는 프로퍼티가 있다.
- constructor 프로퍼티 ⇒ 자신을 생성한 생성자 함수를 카르키는 역할을 한다.
- 다음과 같이 crew라는 객체 리터럴을 만들어 준다면
![]() |
![]() |
자바스크립트의 모든 함수(화살표 함수 제외)생성은 사실 Function 생성자 함수를 통해 이루어진다.
function sum(a, b) {
return a + b;
}
// 이 코드가 내부적으로는
var sum = new Function('a', 'b', 'return a + b')
// Function 생성자 함수를 통해 동작한다는 의미
![]() |
|
비교해 보세요
왜 그러는 걸까? 이를 알아봅시다
crew 생성자 함수를 만들고(리터럴 방식과 혼동 주의), new 연산자로 인스턴스 두개를 만들어본다.
- 두 개의 인스턴스들에게 공통으로 공유할 수 있는 공간을 위하여 Crew의 프로토타입 객체가 생성된 것이다.
- 이로 인해서 공통 변수 선언 및 메모리의 이점을 가질 수 있다.
- Function(), Function.prototype, Crew관계 , Crew, Crew.prototype, 두 개의 인스턴스 관계
- Crew는 Function 생성자 함수를 통해 생성된 함수 객체임과 동시에, 두 개의 인스턴스를 생성하는 생성자 함수가 된다
proto , prototype 비교 정리
- __proto__ 는 객체 안에 존재하는 숨겨진 프로퍼티
- prototype은 오직 function안에 존재하는 참조값
- 인스턴스는 __proto__를 통해 생성자 함수의 prototype에 접근하여 필요한 여러가지 값과 메서드를 사용할 수 있다.
function Test(){};
const obj = new Test();
console.log(obj.prototype); // undefined
console.log(obj.__proto__ === Test.prototype); // true
참조 관계
원형 객체의 프로퍼티를 물려받는다는 표현으로 상속을 사용하겠습니다
다른 객체를 바탕으로 만들어진 객체
![]() |
|
객체의 연결 임의 설정
let animal = {
eats: true
};
let rabbit = {
jumps: true
};
rabbit.__proto__ = animal; // (*)
// 프로퍼티 eats과 jumps를 rabbit에서도 사용할 수 있게 되었다.
alert( rabbit.eats ); // true (**)
alert( rabbit.jumps ); // true
Class문법과 extends
클래스 문법, (Syntactic sugar)
function Robot(name) {
this.name = name;
}
Robot.prototype.sayYourName = function () {
console.log(`삐리비리. 제 이름은 ${this.name}입니다. 주인님.`);
}
//위 아래 비교
class Robot {
constructor(name) {
this.name = name;
}
sayYourName() {
console.log(`삐리비리. 제 이름은 ${this.name}입니다. 주인님.`);
}
}
클래스의 상속과 확장, extends
- 상속을 받는 클래스는 ‘파생 클래스’(derived classes)라고 부른다.
- 부모 클래스의 프로퍼티를 상속받기 위해 constructor안에서 super를 사용한다.
super 사용시 주의할 점
- 만약 파생 클래스에 기본 생성자가 아닌 생성자를 사용하고 싶다면 반드시 super 함수를 사용해야 한다.
- 파생클래스에 사용자 정의 생성자가 없다면 기본 생성자에서 super 함수가 자동으로 호출된다.
- 생성자 함수에서 this 값을 사용할 경우 super 함수는 반드시 this 보다 먼저 실행되어야 한다.
- 파생 클래스가 아닌 클래스에서 사용하면 에러가 발생한다.
class BabyRobot extends Robot {
constructor(name) {
super(name);
this.ownName = '아이크';
}
sayBabyName() {
// 또한 상속을 받게되면 부모 클래스의 메소드를 사용할 수 있게 됩니다.
// 때문에 this로 접근 할 수 있습니다.
this.sayYourName();
console.log('Suceeding you, Father!');
}
}
출처
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Object/create
https://developer.mozilla.org/ko/docs/Web/JavaScript/Inheritance_and_the_prototype_chain
https://www.geeksforgeeks.org/difference-between-proto-and-prototype/
https://ko.javascript.info/prototype-inheritance
https://www.youtube.com/watch?v=TqFwNFTa3c4