6. 프로토타입
- 자바스크립트는 프로토타입 기반 언어.
- 프로토타입 기반 언어는 어떤 객체를 원형(prototype)으로 삼고 이를 복제(참조)함으로써 상속과 비슷한 효과를 얻음.
cf) 클래스 기반 언어 : '상속'을 사용.
1. 프로토타입의 개념 이해
- 어떤 생성자 함수(Constructor)를 new 연산자와 함께 호출하면
- Constructor에서 정의된 내용을 바탕으로 새로운 인스턴스가 생성됨.
- 이때 인스턴스에는
__proto__
라는 프로퍼티가 자동으로 부여되는데
- 이는 Constructor의
prototype
이라는 프로퍼티를 참조.
prototype
과 이를 참조하는 __proto__
는 객체.
prototype
객체 내부에는 인스턴스가 사용할 메서드를 저장. 인스턴스는 __proto__
를 통해 이 메서드들에 접근할 수 있다.
__proto__
는 생략 가능한 프로퍼티
- 어떤 생성자 함수(Constructor)를 new 연산자와 함께 호출하면
- Constructor에서 정의된 내용을 바탕으로 새로운 인스턴스가 생성됨.
- 이때 인스턴스에는
__proto__
라는 프로퍼티가 자동으로 부여되는데 - 이는 Constructor의
prototype
이라는 프로퍼티를 참조.
prototype
과 이를 참조하는 __proto__
는 객체.prototype
객체 내부에는 인스턴스가 사용할 메서드를 저장. 인스턴스는 __proto__
를 통해 이 메서드들에 접근할 수 있다. __proto__
는 생략 가능한 프로퍼티=> 인스턴스에서 __proto__
없이 바로 메서드를 쓸 수 있다. (this가 인스턴스가 되도록!)
=> Constructor.prototype의 메서드들을 자신의 메서드인 것처럼 호출할 수 있다.
var Person = function(name) { this._name = name; }; Person.prototype.getname = function() { return this._name }; var suzi = new Person('Suzi'); suzi.__proto__.getName() //undefined
suzi.__proto__.getName -> suzi(.__proto__).getName //'.__proto__' 생략 가능 -> suzi.getName // getName 함수의 this는 'suzi'
정리
- 자바스크립트는 함수에 자동으로 객체인 prototype 프로퍼티를 생성해놓음.
- 해당 함수를 생성자 함수로 사용할 경우(= new 연산자와 함께 함수를 호출할 경우), 그로부터 생성된 인스턴스에는 숨겨진 프로퍼티인
__proto__
가 자동으로 생성.- 이 프로퍼티는 생략 가능.
=> 생성자 함수의 prototype에 어떤 메서드나 프로퍼티가 있다면 인스턴스에서도 마치 자신의 것처럼 해당 메서드나 프로퍼티에 접근 가능.
1-2. constructor 프로퍼티
-
생성자 함수의 프로퍼티인 prototype 객체 내부에는 constructor 프로퍼티 존재.
-
인스턴스의
__proto__
객체 내부에도 마찬가지. -
constructor 프로퍼티는 생성자 함수(자기 자신)을 참조.
-
constructor 프로퍼티는 읽기 전용 속성이 부여된 예외적인 경우(기본형 리터럴 변수 - number, string, boolean)를 제외하고는 값을 바꿀 수 있다.
=> 어떤 인스턴스의 생성자 정보를 알아내기 위해 constructor 프로퍼티에 의존하는 게 항상 안전하지는 않음.
다양한 constructor 접근 방법
- 모두 동일한 대상(생성자 함수, constructor)을 가리킴.
[Constructor] [instance].__proto__.constructor [instance].constructor Object.getPrototypeOf([instance]).constructor [Construntor].prototype.constructor
2. 프로토타입 체인
2-1. 메서드 오버라이드
- 인스턴스가 생성자 함수의 prototype에 있는 것과 동일한 이름의 프로퍼티 또는 메소드를 가지고 있는 경우
=> 자바스크립트 엔진은 먼저 자신의 프로퍼티를 검색하고, 없으면 그 다음으로 가까운 대상인 __proto__
를 검색. (가까운 순으로)
- 메서드 위에 메서드를 덮어씌웠다. (원본이 그대로 있는 상태에서 다른 대상을 그 위에 얹음)
메서드 오버라이딩이 이뤄져 있는 상황에서 prototype에 있는 메서드에 접근하는 방법
=> 자바스크립트 엔진은 먼저 자신의 프로퍼티를 검색하고, 없으면 그 다음으로 가까운 대상인
__proto__
를 검색. (가까운 순으로): call 또는 apply로 해결.
var Person = fucntion(name) { this.name = name; }; Person.prototype.getName = function() { return this.name; }; var iu = new Person('지금'); iu.getName = function () { return '바로' + this.name; }; console.log(iu.getName()); //바로 지금 console.log(iu.__proto__.getName.call(iu)); //지금
2-2. 프로토타입 체인
- prototype 객체는 객체(Object).
=> 모든 객체의__proto__
에는 Object.prototype이 연결.
Array.prototype : '객체'이므로 Object의 인스턴스다. => Object.prototype을 참조.
-
프로토타입 체이닝 :
__proto__
안에 다시__proto__
를 찾아가는 과정. -
어떤 메서드를 호출하면 자바스크립트 엔진은 데이터 자신의 프로퍼티들을 검색해서 해당 메서드가 있으면 그 메서드를 실행하고, 없으면
__proto__
를 검색해서 있으면 실행하고, 없으면 다시__proto__
를 검색해서 실행. -
__proto__
방향을 계속 찾아가다 보면 최종적으로는 Objsct.prototype에 당도하게 된다.
=> 자바스크립트 데이터는 모두 우측 꼭짓점에 무조건 Object.prototype이 있는 프로토타입 체인 구조를 지닌다.
2-3. 객체 전용 메서드의 예외사항
-
Object.prototype에는 다른 데이터 타입도 접근 가능하기 때문에 객체에서만 사용할 메서드는 Object.prototype이 아닌 Object에 스태틱 메서드로 부여.
-
Object.prototype에는 어떤 데이터에서도 활용할 수 있는 범용적인 메서드들만 있다. (toString, hasOwnProperty, isPrototypeOf 등)
-
Object.create(null) :
__proto__
가 없는 객체를 생성. (내장 메서드 및 프로퍼티들이 제거됨으로써 기본 기능에 제약이 생긴 대신, 객체 자체의 무게가 가벼워짐으로써 성능상 이점을 가짐)
2-4. 다중 프로토타입 체인
- 대각선의
__proto__
를 연결하는 방법 : 생성자함수의 prototype(=__proto__
가 가리키는 대상)이, 연결하고자 하는 상위 생성자 함수의 인스턴스를 바라보게끔 해주면 된다.
- 프로토타입 체이닝은 반드시 2단계로만 이뤄지는 것이 아니라 무한대의 단계를 생성할 수 있다.
Author And Source
이 문제에 관하여(6. 프로토타입), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@pika/코어-자바스크립트-6.-프로토타입저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)