Prototype

PYG·2021년 5월 18일

OOP

목록 보기
6/8

Prototype

  • javascript를 prototype based language라고도 부른다
  • Prototype도 객체이다
  • 생성자를 통해 만든 객체 모두가 공통적으로 사용하는 속성, 함수를 만드는 것
  • javascipt의 모든 객체는 부모 역할을 하는 객체와 연결되어 있다
  • 상속의 개념과 같이 부모 객체의 프로퍼티 혹은 메소드를 상속 받아 사용 가능
  • 부모 역할을 하는 객체를 Prototype이라고 한다
  • prototype은 함수를 정의할 때 object 형태로 생성
  • constructor와 __proto__ 속성을 가지고 있다

1. 객체는 함수로 생성

javascript에서 함수는 객체이다

javascript의 함수는 객체이기 때문에 프로퍼티를 가질 수 있다

let a = {}; 
let a = new Object(); 
function Person(){}  
let Person = new Function(); 

1.1 prototype object

function Ultra() {};
  • 함수를 정의하면 prototype 객체가 같이 생성된다
  • prototype 객체는 constructor와 __proto__ 프로퍼티를 가진 객체이다
function Ultra() {};
Super = new Ultra();
->
prototype: {constructor: ƒ} 
constructor: ƒ Ultra()
__proto__: Object
    1. Ultra 함수 정의 후 prototype 객체 안에 함수가 생성되었다
    1. new 생성자를 사용해 Super라는 변수 안에 생성된 함수를 Ultra라는 이름으로 객체 생성
    1. 그 객체 안에 Ultra라는 이름의 함수 constructor와 Object라는_proto_가 생성됐다

1.2 constructor

  • 어떠한 객체가 누구로부터 만들어졌는지 알려준다
  • 주류 객체지향에서는 어떠한 객체의 class가 뭔지 알려준다
  • 새로운 객체를 만들어 낼 수도 있다
    -ex) b = new d.constructor()
var a = new Date();
Date.prototype.constructor === Date //-> true 
a.constructor //-> f Date(){} 
//a를 누가 만든 객체인지 모를 때 constructor 이용
//a는 자체적으로 constructor를 가지고 있지 않기 때문에 
//__proto__를 따라 constructor function의 prototype object로
//가서 거기에 있는 constructor라는 프로퍼티를 통해서 
//자신을 생성해준 생성자를 뱉어낸다
b = new d.constructor() / b = new Date() //-> 같은 코드이다 

1.3 __proto__

  • __proto__는 prototype link이다
  • 자기 자신을 생성한 함수의 prototype object에 접근하기 위한 prototype link이다
  • [[Prototype]]와 같은 개념
  • 부모와 연결돼 있는 것은 __proto__
  • __proto__ 속성은 객체를 생성한 함수의 prototype object를 가리킨다
function Ultra() {};
Ultra.prototype.name = 'bora';
Ultra.prototype.age = 20;
Super = new Ultra();
console.log(Super.name); -> bora
console.log(Super.age); -> 20
    1. Ultra라는 함수를 정의하니 prototype 객체가 생성
    1. 생성된 prototype 객체에 name이 bora, age가 20인 프로퍼티를 대입
    1. Super 변수에 Ultra 객체 대입
    1. Super의 name과 age를 불러오니 bora와 20이 출력
    1. Super에는 아무런 값도 주지 않았는데 왜 이와 같은 값이 출력되었을까
    1. Super가 가진 __proto__속성 즉 prototype link 때문
    1. Sub = new Ultra(); 후 console.log(Sub.name)을 줘도 값은 bora가 출력
function Ultra() {};
Ultra.prototype.name = 'bora';
Ultra.prototype.age = 20;
Super = new Ultra(); 
Sub = new Ultra();
Sub.name = 'gogo';
Sub.age = 30; 
console.log(Super.name); -> 'bora'
console.log(Super.age); -> 20
console.log(Sub.name); -> 'gogo'
console.log(Sub.age); -> 30
    1. Super에는 값을 할당하지 않고 Sub에 따로 값을 할당했다
    1. Super는 빈 객체(name과 age라는 속성이 없기)이기 때문에 name과 age 속성을 찾을 때까지 __proto__와 연결된 prototype object를 참조
    1. 최상위 prototype object까지 가서도 못 찾을 경우 undefined 출력

1.4 prototype chain

  • 특정 객체의 프로퍼티나 메소드 접근 시 그 객체에 해당 프로퍼티나 메소드가 존재하지 않을 경우 __proto__가 가리티는 링크르 따라 부모 역할을 하는 prototype object의 프로퍼티나 메소드를 타고 올라가는 것 - prototype 체이닝
  • 가장 최상위는 Object.prototype -> 여기에도 없으면 undefined 출력
  • 하위 객체는 상위 객체의 프로퍼티나 메소드를 상속 받는 게 아니라 공유
function Ultra() {}
Ultra.prototype.ultraProp = true;
function Super() {}
Super.prototype = new Ultra();
function Sub() {}
Sub.prototype = new Super();
var o = new Sub();
console.log(o.ultraProp);
  • Ultra 함수를 정의한 후 prototype 객체 안에 ultraProp와, Ultra()라는 constructor가 생성됐다
  • Sub라고하는 함수는 객체이기 때문에 프로퍼티를 가지고 잇을 수 있다
  • 그 프로퍼티 중에서 prototype이라는 특수한 프로퍼티가 있어서 이 prototype이라는 프로퍼티 안에는 어떠한 객체가 정의가 돼 있다 (객체가 들어가 있다)
  • Sub.prototype.name = 'baro'
    -> prototype 객체 안에 name이라는 프로퍼티가 있고 그 값이 baro다
  • 그렇게 객체를 저장해 놓은 후 나중에 new를 이용해서 생성자를 호출하게 되면 javascript는 이 생성자 함수(Sub)의 prototype 프로퍼티에 저장돼 있는 객체를 꺼내서 그것을 return해 준다
  • Sub.prototype = new Super();
    -> Super 생성자가 만든 객체가 이 안에 들어간다
  • 서로가 서로에 연결되어 있는 것을 Prototype chain이라고 한다

2. 생성자 및 함수 정의

  • 생성자 안에서 메소드를 만드는 것이 갖는 단점 : 생산성이 많이 떨어진다
  • 생성자를 이용해서 만든 객체가 공통적으로 사용하는 함수 혹은 속성을 만들 수 있으면 얼마나 좋을까

2.1

function Person(name, first, second){
    this.name = name;
    this.first = first;
    this.second = second;
};
Person.prototype.sum = function() {
    return 'prototype : '+ (this.first + this.second);
}
var park = new Person('park', 20, 30);
var lee = new Person('lee', 30, 40);
  • 생성자 안에 함수 정의가 들어있지 않기 때문에 park, lee 등 변수의 객체를 만들 때는 함수가 실행되지 않는다

2.2

  • 함수를 호출할 때, 한 번만 실행이 된다
  • 성능 절약, 메모리 절약
console.log(park.sum());
console.log(lee.sum());

-> prototype : 50
prototype : 70

2.3

  • 수많은 객체 중 park라는 변수가 가리키는 객체의 메소드를 다르게 동작하고 싶을 때
function Person(name, first, second){
    this.name = name;
    this.first = first;
    this.second = second;
};
Person.prototype.sum = function() {
    return 'prototype : '+ (this.first + this.second);
}
var park = new Person('park', 20, 30);
park.sum = function() {
    return 'this : '+ (this.first + this.second);
}
var lee = new Person('lee', 30, 40);
console.log(park.sum());
console.log(lee.sum());

-> this : 50
prototype : 70

  • javascript는 park라는 객체의 sum이라는 메소드를 호출할 때 제일 먼저 그 객체 자신이 sum이라고 하는 속성(함수)을 가지고 있는지 찾는다
    있으면 실행시키고 끝
  • lee라는 객체는 자신 sum이라는 메소드를 갖고 있지 않으면 이 객체의 생성자인 Person의 prototype 객체에 sum이라고 하는 메소드가 정의돼 있는지 찾고 있으면 그것을 실행한다

0개의 댓글