[JS] Prototypes 프로토타입

Hyodduru ·2021년 12월 27일
0

JavaScript

목록 보기
50/60

프로토타입 기반 언어?

JavaScript는 흔히 프로토타입 기반 언어(prototype-based language)라 불립니다.— 모든 객체들이 메소드와 속성들을 상속 받기 위한 템플릿으로써 프로토타입 객체(prototype object)를 가진다는 의미입니다. 프로토타입 객체도 또 다시 상위 프로토타입 객체로부터 메소드와 속성을 상속 받을 수도 있고 그 상위 프로토타입 객체도 마찬가지입니다. 이를 프로토타입 체인(prototype chain)이라 부르며 다른 객체에 정의된 메소드와 속성을 한 객체에서 사용할 수 있도록 하는 근간입니다.

정확히 말하자면 상속되는 속성과 메소드들은 각 객체가 아니라 객체의 생성자의 prototype이라는 속성에 정의되어 있습니다.

JavaScript에서는 객체 인스턴스와 프로토타입 간에 연결(많은 브라우저들이 생성자의 prototype 속성에서 파생된 proto 속성으로 객체 인스턴스에 구현하고 있습니다.)이 구성되며 이 연결을 따라 프로토타입 체인을 타고 올라가며 속성과 메소드를 탐색합니다.

Constructor Functions and the new Operator

참고) constructor function 은 JS language의 특징 아님.
Instead, they are simply a pattern that has been developed by other developers. And now everyone simply uses this.

firstName과 birthYear은 Instace properties이다. Person이라는 constructor function을 통하여 만들어진 모든 instances들의 properties가 될 것이기 때문.

const Person = function (firstName, birthYear) {
  // Instance properties 
  this.firstName = firstName;
  this.birthYear = birthYear;

  // Never do this - 절대 constructor function 내에 method 만들지 말 것! 
  여러개의 Person object 만들 시 method도 여러개 만들어짐 -> 좋지 못한 코드
  //   this.calcAge = function () {
  //     console.log(2037 - this.birthYear);
  //   };
};

const jonas = new Person('Jonas', 1991); 
// Jonas is an instance of Person

console.log(jonas);
//Person
//{birthYear: 1991
//firstName: "Jonas"}

const matilda = new Person('Matilda', 2017);
const jack = new Person('Jack', 1975);
console.log(matilda, jack);

console.log(jonas instanceof Person); //true
console.log('jay' instanceof Person); //false

Prototypes

JS 내 모든 함수들은 자동적으로 prototype이라 불리는 property를 가진다. (constructor functions를 포함하여) 그렇기에 모든 constructor function을 통하여 만들어진 objects들은 모든 constructors prototype property의 methods와 properties에 접근가능하다.(상속 받는다.)

아래의 method를 만드는 방법은 단 한번의 복사로 다른 object들도 계속해서 이 method를 재사용할 수 있다는 장점이 있다.

Person.prototype.calcAge = function () {
  console.log(2037 - this.birthYear);
};

jonas.calcAge(); //46 object는 만들어진 constuctor function의 prototype에 대한 접근이 가능하므로! (prototypal inheritance)
matilda.calcAge(); //20

console.log(jonas.__proto__); //{calcAge: ƒ, constructor: ƒ}
// prototype of the Jonas object is essentially the prototype property of the constructor function.
console.log(jonas.__proto__ === Person.prototype); //true
//주의사항. 꼭 알아둘 것!) 
//Person.prototype 은 Person의 prototype이 아니다. 
//모든 Person constructor function의 object들의 prototype으로 사용되는 것임.

console.log(Person.prototype.isPrototypeOf(jonas)); //true
console.log(Person.prototype.isPrototypeOf(matilda)); //true
console.log(Person.prototype.isPrototypeOf(Person)); //false

// .prototypeOfLinkedObjects

Person.prototype.species = 'Homo Sapiens';
console.log(jonas.species, matilda.species);
//Homo Sapiens Homo Sapiens
console.log(jonas);
//Person {firstName: 'Jonas', birthYear: 1991}
// species가 jonas자체의 property는 아님.
// 단순히 'species' property 에 접근할 수 있는 것임!

console.log(jonas.hasOwnProperty('firstName')); //true
console.log(jonas.hasOwnProperty('speices')); //false

Prototypal Inheritance and The Prototype Chain

How Prototypal Inheritance and Delegation works

Constructor function[Person()] ---.prototype --> Prototype[Person.prototype] <-- prototype inheritance / delegation-- .__proto object [jonas]

주의할 점) Person.prototype은 Person의 prototype이 아닌, Person으로부터 만들어진 새로운 객체들의 prototype을 가리킨다.

The new Operator
1. New {} (the empty object) is created
2. constructor function내의 this는 {}(새로 만들어진 객체)를 가리킨다.
3. 새로운 객체는 constructor function의 prototype에 대한 link를 갖는다.
4. function은 자동적으로 새로운 객체를 return한다.

The prototype chain


[Object()] : Built-in constructor function for objects. This is used when we write an object literal.
{...} === new Object(...)

[person.prototype] 이 것 자체도 object. JS내에서 object는 모두 property를 가지고 있다.

ex) jonas.hasownproperty('name') // true
hasownproperty라는 method는 Object 자체 내에 있다. 그렇기에 이 함수를 사용할 수 있는 것! -> prototype chain

Prototypal Inheritace on Built-In Objects

console.log(jonas.__proto__); //Person.prototype
console.log(jonas.__proto__.__proto__); //Object.prototype
console.log(jonas.__proto__.__proto__.__proto__); // null -> Object is the top of the prototype chain

console.dir(Person.prototype.constructor);

const arr = [3, 4, 4, 2, 1, 5, 5, 7, 8, 0]; // new Array === []
console.log(arr.__proto__); // array의 모든 methods
console.log(arr.__proto__ === Array.prototype); //true

console.log(arr.__proto__.__proto__); // Object.prototype

Array.prototype.unique = function () {
  return [...new Set(this)];
};
console.log(arr.unique()); //[3, 4, 2, 1, 5, 7, 8, 0]
// 위의 방법 실제로 하는 것 좋은 건 아님  bugs

const h1 = document.querySelector('h1');
// h1의 prototype : htmlElement,
//htmlElement의 prototype : element, element의 prototype : node, 
//node의 prototype : EventTarget Eventtarget의 prototype : Object  
//=> huge prototype chain
profile
꾸준히 성장하기🦋 https://hyodduru.tistory.com/ 로 블로그 옮겼습니다

0개의 댓글