2021. 8. 5. 16:13ㆍCSE/Java Script
<프로토타입 체이닝>
1. 프로토타입의 두 가지 의미
- 자바스크립트는 프로토타입 가븐의 객체지향 프로그래밍을 지원한다
- 자바스크립트는 클래스 개념이 없기 때문에 객체 리터럴이나 생성자 함수로 객체를 생성한다.
=> 이 때, 생성된 객체의 부모 객체가 '프로토타입' 객체이다.
=> 모든 객체는 프로토타입 객체를 가리키는 '암묵적 프로토타입 링크'([[Prototype]] 링크)가 있다
=> 객체지향의 상속처럼 부모 객체가 가진 프로퍼티나 메서드 사용 가능
- 함수 객체의 prototype 프로퍼티와 객체의 숨은 프로퍼티인 [[Prototype]]을 구분해야 한다
=> 이를 위해 자바스크립트의 객체 생성 규칙을 알아야 한다.
=> 모든 객체는 자신을 생성한 생성자 함수의 prototype 프로퍼티가 가리키는 프로토타입 객체를 자신의 부모객체로 설정하는 [[Prototype]]링크로 연결한다.
- Person() 생성자 함수는 prototype 프로퍼티로 자신과 링크된 프로토타입 객체(Person.prototype)를 가리킨다.
=> foo 객체는 Person() 함수의 프로토타입 객체를 [[Prototype]] 링크로 연결한다.
=> Person의 prototype == foo의 [[Prototype]]
2. 객체 리터럴 방식으로 생성된 객체의 프로토타입 체이닝
- 프로토타입 체이닝은 객체가 자신의 프로토타입 객체의 프로퍼티와 메서드를 자신의 것 처럼 접근할 수 있도록 한다.
var myObject={
name : 'foo',
sayName : function(){
console.log('My Name is '+ this.name);
}
};
myObject.sayName(); //My Name is foo
console.log(myObject.hasOwnProperty('name')); //true
=> 따라서 foo도 자신의 프로토타입 객체인 Object.prototype의 hasOwnProperty()라는 메서드를 사용할 수 있다.
3. 생성자 함수로 생성된 객체의 프로토타입 체이닝
function Person(name){
this.name = name;
}
var foo = new Person('foo');
console.log(foo.hasOwnProperty('age')); //false
- foo의 프로토타입 객체인 Person.prototype은 프로토타입 객체로 Object.prototype을 갖는다.
=> 따라서 foo도 Object.prototype의 메서드인 hasOwnProeprty()를 사용할 수 있다.
4. 프로토타입 체이닝의 종점
- Object.prototype 객체는 프로토타입 체이닝의 종점이다
=> 모든 자바스크립트 객체는 프로토타입 체이닝으로 Object.prototype 객체가 가진 프로퍼티와 메서드에 접근할 수 있다.
=> 따라서 Object.prototype에는 모든 객체가 호출 가능한 표준 메서드들이 정의되어 있다
5. 기본 데이터 타입 확장
- 자바스크립트의 숫자, 문자열, 배열 등에서 사용되는 표준 메서드들의 경우, 이들의 프로토타입인 Number.prototype, String.prototype, Array.prototype 등에 정의되어있다.
=> 그리고 이런 기본 내장 프로토타입 객체 또한 Object.prototype을 프로토타입으로 가지고 있다.
- 자바스크립트는 기본 내장 프로토타입 객체에도 사용자가 메서드를 추가하는 것을 허용한다.
=>추가된 메서드는 해당 프로토타입 객체를 프로토타입으로 갖는 모든 객체들이 사용할 수 있다.
String.prototype.testMethod = function () {
console.log('This is the String.prototype.testMethod()');
};
var str = "this is test";
str.testMethod(); //This is the String.prototype.testMethod()
6. 프로토타입도 자바스크립트 객체다
- 프로토타입 객체도 자바스크립트 객체이므로 프로퍼티를 추가/삭제하는 것이 가능하다.
=> 프로퍼티를 추가/삭제한 결과는 실시간으로 프로토타입 체이닝에 반영된다.
function Person(name){
this.name = name;
}
var foo = new Person('foo');
//foo.sayHello(); // 에러 발생
Person.prototype.sayHello = function(){
console.log('Hello');
}
foo.sayHello(); //Hello
7. 프로토타입 메서드와 this 바인딩
- 프로토타입 객체는 메서드를 가질 수 있다. => 프로토타입 메서드
- 프로토타입 메서드의 내부에서 this를 사용하면 해당 this는 뭘 가리킬까?
=> 호출한 객체를 가리킴
function Person(name){
this.name = name;
}
Person.prototype.getName = function(){
console.log(this.name);
}
var foo = new Person('foo');
foo.getName(); //foo
Person.prototype.name = 'person';
Person.prototype.getName(); //person
foo.getName(); //foo
8. 디폴트 프로토타입은 다른 객체로 변경이 가능하다.
- 함수를 생성할 대, 해당 함수와 연결되는 디폴트 프로토타입 객체를 다른 객체로 변경하는 것이 가능하다.
=> 객체지향의 상속을 구현할 수 있다.
- 변경된 시점 이후에 생성된 객체들은 변경된 프로토타입 객체로 [[Prototype]] 링크를 연결하지만, 변경된 시점 전에 생성된 객체는 기존의 프로토타입 객체로 [[Prototype]] 링크 연결을 유지하고 있다.
function Person(name){
this.name;
}
console.log(Person.prototype.constructor); //Person(name)
var foo = new Person('foo');
console.log(foo.country); //undefined
Person.prototype = {
country:'Korea'
}; //프로토타입 객체 변경
console.log(Person.prototype.constructor);
//Person.prototype에 construdtor가 없어서 프로토타입 체이닝을 통해 Object.prototoype.constructor 출력
//=> Object()
var bar = new Person('bar');
console.log(foo.country); //undefined
console.log(bar.country); //korea
console.log(foo.constructor); //Person(name)
console.log(bar.constructor); //Object()
** 객체의 프로퍼티 읽기나 메서드를 실행할때만 프로토타입 체이닝이 된다.
=> 객체의 특정 프로퍼티에 값을 쓰려고 할 때에는 프로토타입 체이닝이 일어나지 않는다.
'CSE > Java Script' 카테고리의 다른 글
[Java Script] 스코프 체인 (0) | 2021.09.06 |
---|---|
[Java Script] 실행 컨텍스트 (0) | 2021.08.05 |
[Java Script] 함수와 프로토타입 체이닝 3 (0) | 2021.08.05 |
[Java Script] 함수와 프로토타입 체이닝 2 (0) | 2021.08.02 |
[Java Script] 함수와 프로토타입 체이닝 1 (0) | 2021.07.30 |