Javascript는 흔히 프로토타입 기반 언어(prototype-based language) 라고 불리는데, 이는 모든 객체들이 메서드와 속성들을 상속받기 위한 템플릿으로서 프로토타입 객체를 가진다는 의미이다.
프로토타입 객체도 또 다시 상위 프로토타입 객체로부터 메소드와 속성을 상속받을수도 있고, 그 상위 프로토타입 객체도 마찬가지이다. 이를 프로토타입 체인(prototype chain) 이라고 부르며, 다른 객체에 정의된 메서드와 속성을 한 객체에서 사용할 수 있도록 한다.
사실 우리는, 이미 객체 지향적 방법을 사용하고 있었다.
우리가 그동안 만들었던 배열도 전부 Array
의 인스턴스이다.
모든 객체는 프로토타입이라는 다른 객체를 가리키는 내부 링크를 가지고 있다.
Array.prototype
을 콘솔창에 입력하면 다음과 같은 결과가 나타난다.
MDN에도 array의 메서드를 검색하면 Array.prototype.map()
이라고 나오는 것을 확인할 수 있는데, 이는 Array를 상속받은 객체에서 사용 가능한 수많은 메서드들이 Array의 prototype 속성에 정의되어 있기 때문이다.
new
연산자와 생성자 함수를 사용하면, 유사한 객체 여러 개를 쉽게 만들 수 있다.
생성자 함수(constructor function)와 일반 함수에 기술적 성능 차이는 없다.
new
연산자를 붙여 실행할 것클래스 Human과 인스턴스, 프로토타입의 관계는 다음 그림과 같다.
__proto__
Object.prototype
의 __proto__
속성은, 접근하고자 하는 객체의 내부 속성인 [[Prototype]] 를 노출하는 접근자 속성이다.
새로운 객체를 생성할 때, 객체의 프로퍼티와 함께 __proto__
프로퍼티가 같이 생성된다.
내가 만약 const obj = {key: value}
라는 객체를 생성했다면, obj.prototype을 통해 prototype 객체에 접근이 가능하고, obj.__proto__
를 통해서도 obj의 prototype 객체에 접근이 가능하다.
객체지향프로그래밍의 특성중, 상속 을 구현할 때에 프로토타입 체인을 사용한다.
let jangjiwoo = new Human('장지우', 26);
// 속성
jangjiwoo.age;
jangjiwoo.gender;
// 메서드
jangjiwoo.eat();
jangjiwoo.sleep();
학생과 사람이라는 클래스가 각각 존재한다고 가정했을 때, 학생도 사람이기 때문에 Human
클래스의 기본적인 메서드를 상속받을 수 있다.
하지만 모든 메서드가 겹치는 것은 당연히 아니기 때문에 추가적인 특징도 필요하다.
let jangjiyeon = new Student('장지연', 30);
// 속성
jangjiyeon.grade;
// 메서드
jangjiyeon.learn();
위 예시의 jangjiyeon
은 Student이다. Student는 Human의 특징을 그대로 물려받는다. (age, gender와 같은 속성이 겹치기 때문이다)
이렇게 속성과 메서드를 물려주는 클래스를 부모클래스(Human
), 속성과 메서드를 물려받는 클래스를 자식클래스(Student
), 그리고 이 과정을 상속이라고 한다.
const div = document.createElement('div');
div.__proto__ //HTMLDivElement
div.__proto__.__proto__ //Element
div.__proto__.__proto__.__proto__ //Node
div.__proto__.__proto__.__proto__.__proto__ //EventTarget
이런식으로 프로토타입 체인을 직접 확인해 볼 수도 있다.