πŸ€·πŸ»β€β™€οΈ μžλ°”μŠ€ν¬λ¦½νŠΈ μƒμ†μ˜ 핡심 원리, ν”„λ‘œν† νƒ€μž…

졜호빈·2025λ…„ 6μ›” 17일
1
post-thumbnail

ν”„λ‘œν† νƒ€μž…μ΄λž€?

μžλ°”μŠ€ν¬λ¦½νŠΈλŠ” ν”„λ‘œν† νƒ€μž… 기반으둜, functionκ³Ό prototype으둜 상속을 κ΅¬ν˜„ν•œλ‹€.

function Animal(name) {
  this.name = name;
}
Animal.prototype.speak = function () {
  console.log(this.name + ' makes a noise.');
};

function Dog(name) {
  Animal.call(this, name); // 상속
}
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;

const dog = new Dog('Buddy');
dog.speak(); // Buddy makes a noise.

ν•˜μ§€λ§Œ 이 방법은 클래슀 기반 μ–Έμ–΄(C++, Java λ“±)에 μ΅μˆ™ν•œ κ°œλ°œμžλ“€μ—κ²ŒλŠ” λ³΅μž‘ν•˜λ‹€. κ·Έλž˜μ„œ ES6λΆ€ν„° class 문법이 λ„μž…λ˜μ—ˆλ‹€. class 문법은 μƒˆλ‘œμš΄ 객체지ν–₯ λͺ¨λΈμ„ μ œκ³΅ν•˜λŠ” 것이 μ•„λ‹ˆλ©°, ν΄λž˜μŠ€λ„ 사싀은 ν•¨μˆ˜μ΄λ‹€. 단지 κΈ°μ‘΄ 방식을 더 읽기 μ’‹κ³  μ“°κΈ° νŽΈν•˜κ²Œ λ°”κΎΌ 것일 뿐이닀.





ν”„λ‘œν† νƒ€μž… 객체

μžλ°”μŠ€ν¬λ¦½νŠΈμ˜ λͺ¨λ“  κ°μ²΄λŠ” μžμ‹ μ˜ λΆ€λͺ¨ 역할을 λ‹΄λ‹Ήν•˜λŠ” 객체와 μ—°κ²°λ˜μ–΄ μžˆλ‹€. 그리고 이것은 마치 객체 μ§€ν–₯의 상속 κ°œλ…κ³Ό 같이 λΆ€λͺ¨ 객체의 ν”„λ‘œνΌν‹° λ˜λŠ” λ©”μ†Œλ“œλ₯Ό 상속받아 μ‚¬μš©ν•  수 있게 ν•œλ‹€. μ΄λŸ¬ν•œ λΆ€λͺ¨ 객체λ₯ΌΒ Prototype(ν”„λ‘œν† νƒ€μž…) κ°μ²΄Β λ˜λŠ” μ€„μ—¬μ„œ Prototype(ν”„λ‘œν† νƒ€μž…)이라 ν•œλ‹€.

Prototype κ°μ²΄λŠ” μƒμ„±μž ν•¨μˆ˜μ— μ˜ν•΄ μƒμ„±λœ 각각의 객체에 곡유 ν”„λ‘œνΌν‹°λ₯Ό μ œκ³΅ν•˜κΈ° μœ„ν•΄ μ‚¬μš©ν•œλ‹€.

let student = {
  name: 'Lee',
  score: 90
};

console.log(student.hasOwnProperty('name')); // true
console.dir(student);

studentμ—λŠ” hasOwnProperty λ©”μ†Œλ“œκ°€ μ—†μ§€λ§Œ λ™μž‘ν•  수 μžˆλŠ” μ΄μœ λ„ student의 ν”„λ‘œν† νƒ€μž…μ΄ Object이기 λ•Œλ¬Έμ΄λ‹€. Objectμ—λŠ” hasOwnProperty λ©”μ†Œλ“œκ°€ 있기 λ•Œλ¬Έμ— studentκ°€ 이λ₯Ό μ‚¬μš©ν•  수 μžˆλŠ” 것이닀.

constructor ν”„λ‘œνΌν‹°

ν”„λ‘œν† νƒ€μž… κ°μ²΄λŠ” constructor ν”„λ‘œνΌν‹°λ₯Ό κ°–λŠ”λ‹€. 이 constructor ν”„λ‘œνΌν‹°λŠ” 객체의 μž…μž₯μ—μ„œ μžμ‹ μ„ μƒμ„±ν•œ 객체λ₯Ό 가리킨닀.

예λ₯Ό λ“€μ–΄ Person() μƒμ„±μž ν•¨μˆ˜μ— μ˜ν•΄ μƒμ„±λœ 객체λ₯Ό foo라 ν•˜μž. 이 foo 객체λ₯Ό μƒμ„±ν•œ κ°μ²΄λŠ” Person()μƒμ„±μž ν•¨μˆ˜μ΄λ‹€. μ΄λ•Œ foo 객체 μž…μž₯μ—μ„œ μžμ‹ μ„ μƒμ„±ν•œ κ°μ²΄λŠ” Person() μƒμ„±μž ν•¨μˆ˜μ΄λ©°, foo 객체의 ν”„λ‘œν† νƒ€μž… κ°μ²΄λŠ” Person.prototype이닀. λ”°λΌμ„œ ν”„λ‘œν† νƒ€μž… 객체 Person.prototype의 constructor ν”„λ‘œνΌν‹°λŠ” Person() μƒμ„±μž ν•¨μˆ˜λ₯Ό 가리킨닀.

function Person(name) {
    this.name = name;
}

let foo = new Person("Lee");
// Person() μƒμ„±μž ν•¨μˆ˜μ— μ˜ν•΄ μƒμ„±λœ 객체λ₯Ό μƒμ„±ν•œ κ°μ²΄λŠ” Person() μƒμ„±μž ν•¨μˆ˜μ΄λ‹€.
console.log(Person.prototype.constructor === Person);

// foo 객체λ₯Ό μƒμ„±ν•œ κ°μ²΄λŠ” Person() μƒμ„±μž ν•¨μˆ˜μ΄λ‹€.
console.log(foo.constructor === Person);

// Person() μƒμ„±μž ν•¨μˆ˜λ₯Ό μƒμ„±ν•œ κ°μ²΄λŠ” Function() μƒμ„±μž ν•¨μˆ˜μ΄λ‹€.
console.log(Person.constructor === Function);
  • Person.prototype.constructor === Person은 μžλ™μœΌλ‘œ μ„€μ •λ˜μ–΄ μžˆλ‹€.





μžλ°”μŠ€ν¬λ¦½νŠΈμ˜ λ³΅μž‘ν•œ 생성&ν”„λ‘œν† νƒ€μž… ꡬ쑰

Function을 μ˜ˆμ‹œλ‘œ 생성과 ν”„λ‘œν† νƒ€μž… ꡬ쑰에 λŒ€ν•΄ μ‚΄νŽ΄λ³΄λ €κ³  ν•œλ‹€.

μžλ°”μŠ€ν¬λ¦½νŠΈμ—μ„œ Function은 ν•¨μˆ˜μ΄λ©΄μ„œλ„ μƒμ„±μž ν•¨μˆ˜ 역할도 ν•  수 μžˆλŠ” 객체이닀. μ•„λž˜μ— μžˆλŠ” 것듀이 각각 μ–΄λ–€ 것을 μ˜λ―Έν•˜λŠ”μ§€ μ•Œμ•„λ³΄μž.

Function
Function.__proto__
Function.constructor
Function.prototype
Function.prototype.__proto__
Function.prototype.constructor

  1. Function
  • μžλ°”μŠ€ν¬λ¦½νŠΈμ—μ„œ ν•¨μˆ˜ 생성에 μ‚¬μš©λ˜λŠ” λ‚΄μž₯ μƒμ„±μž ν•¨μˆ˜
  • Function μžμ²΄λ„ ν•¨μˆ˜ 객체이닀. (typeof Function === 'function')
  • λ”°λΌμ„œ, Function은 ν•¨μˆ˜ 객체고, κ·Έ ν•¨μˆ˜ 객체λ₯Ό μƒμ„±ν•œ 것도 Function μƒμ„±μž ν•¨μˆ˜λ‹ˆκΉŒ κ²°κ΅­ Function은 Function의 μΈμŠ€ν„΄μŠ€κ°€ λ˜λŠ” 것이닀. 🀯🀯🀯
console.log(typeof Function); // 'function'
console.log(Function instanceof Function); // true

  1. Function.__proto__
  • Function.prototype을 가리킨닀.
  • μ™œλƒν•˜λ©΄, Function μžμ²΄λŠ” 일단 ν•¨μˆ˜λ‹€. μœ„μ—μ„œ λ§ν–ˆλ“―μ΄ κ·Έ ν•¨μˆ˜ 객체λ₯Ό μƒμ„±ν•œ 것도 Function μƒμ„±μž ν•¨μˆ˜λ‹ˆκΉŒ Function.prototype을 κ°€λ¦¬ν‚€λŠ” 것이닀.
    • μœ„μ—μ„œ μ–ΈκΈ‰ν–ˆμ§€λ§Œ prototype ν”„λ‘œνΌν‹°λŠ” ν•¨μˆ˜ 객체가 μƒμ„±μžλ‘œ μ‚¬μš©λ  λ•Œ 이 ν•¨μˆ˜λ₯Ό 톡해 생성될 객체의 λΆ€λͺ¨ 역할을 ν•˜λŠ” 객체λ₯Ό μ˜λ―Έν•œλ‹€.
console.log(Function.__proto__ === Function.prototype); // true

μ •λ¦¬ν•˜μžλ©΄, Function은 ν•¨μˆ˜μ΄μž μƒμ„±μžμ΄κ³ , Function μžμ‹ μ„ μƒμ„±ν•˜λŠ” μƒμ„±μžμ΄λ©΄μ„œ λΆ€λͺ¨μ—­ν• λ„ ν•˜λŠ”β€¦. 그런 λ³΅μž‘ν•œ ꡬ쑰λ₯Ό κ°€μ§„ κ°μ²΄λΌλŠ” 것이닀.


  1. Function.constructor
  • Function κ°μ²΄λŠ” Function μƒμ„±μžμ— μ˜ν•΄ μƒμ„±λ˜μ—ˆκΈ° λ•Œλ¬Έμ— Function을 가리킨닀.
console.log(Function.constructor === Function); // true

  1. Function.prototype
  • ν•¨μˆ˜λ‘œ λ§Œλ“€μ–΄μ§„ λͺ¨λ“  객체가 λ¬Όλ €λ°›λŠ” ν”„λ‘œν† νƒ€μž… 객체
  • λͺ¨λ“  ν•¨μˆ˜μ˜ 곡톡 κΈ°λŠ₯이 여기에 λ“€μ–΄μžˆλ‹€. (call, apply, bind λ“±)
function foo() {}
console.log(foo.__proto__ === Function.prototype); // true

  1. Function.prototype.__proto__
  • Function.prototype도 결ꡭ은 κ°μ²΄λ‹ˆκΉŒ, κ·Έ λΆ€λͺ¨μΈ Object.prototype 을 가리킨닀.
console.log(Function.prototype.__proto__ === Object.prototype); // true

  1. Function.prototype.constructor
  • Function.prototype은 Function μƒμ„±μžλ‘œ λ§Œλ“€μ–΄μ‘ŒκΈ° λ•Œλ¬Έμ— Function을 가리킨닀.
console.log(Function.prototype.constructor === Function); // true





ν”„λ‘œν† νƒ€μž… 체인

μžλ°”μŠ€ν¬λ¦½νŠΈλŠ” νŠΉμ • 객체의 ν”„λ‘œνΌν‹°λ‚˜ λ©”μ†Œλ“œμ— μ ‘κ·Όν•˜λ €κ³  ν•  λ•Œ ν•΄λ‹Ή 객체에 μ ‘κ·Όν•˜λ €λŠ” ν”„λ‘œνΌν‹° λ˜λŠ” λ©”μ†Œλ“œκ°€ μ—†λ‹€λ©΄ [[Prototype]]이 κ°€λ¦¬ν‚€λŠ” 링크λ₯Ό 따라 μžμ‹ μ˜ λΆ€λͺ¨ 역할을 ν•˜λŠ” ν”„λ‘œν† νƒ€μž… 객체의 ν”„λ‘œνΌν‹°λ‚˜ λ©”μ†Œλ“œλ₯Ό μ°¨λ‘€λŒ€λ‘œ κ²€μƒ‰ν•œλ‹€. 이것을 ν”„λ‘œν† νƒ€μž… 체인이라 ν•œλ‹€.

객체의 ν”„λ‘œνΌν‹°μ— 값을 ν• λ‹Ήν•˜λŠ” 경우, ν”„λ‘œν† νƒ€μž… 체인은 λ™μž‘ν•˜μ§€ μ•ŠλŠ”λ‹€. μ΄λŠ” 객체에 ν•΄λ‹Ή ν”„λ‘œνΌν‹°κ°€ μžˆλŠ” 경우, 값을 μž¬ν• λ‹Ήν•˜κ³  ν•΄λ‹Ή ν”„λ‘œνΌν‹°κ°€ μ—†λŠ” κ²½μš°λŠ” ν•΄λ‹Ή 객체에 ν”„λ‘œνΌν‹°λ₯Ό λ™μ μœΌλ‘œ μΆ”κ°€ν•˜κΈ° λ•Œλ¬Έμ΄λ‹€.

// ν”„λ‘œν† νƒ€μž… 객체 생성
const grandParent = {
    sayHi: function() {
        console.log("Hi from grandparent!");
    }
};

const parent = Object.create(grandParent); // grandParentλ₯Ό ν”„λ‘œν† νƒ€μž…μœΌλ‘œ μ„€μ •
const child = Object.create(parent); // parentλ₯Ό ν”„λ‘œν† νƒ€μž…μœΌλ‘œ μ„€μ •

child.sayHi(); // "Hi from grandparent!"

➑️ child κ°μ²΄μ—λŠ” sayHi λ©”μ†Œλ“œκ°€ μ—†μ§€λ§Œ, child β†’ parent β†’ grandParent μˆœμ„œλ‘œ μ°Ύμ•„κ°€λ©° sayHiλ₯Ό μ΅œμ’…μ μœΌλ‘œ grandParentμ—μ„œ μ°Ύμ•„ ν˜ΈμΆœν•  수 μžˆλ‹€.


1. 객체 λ¦¬ν„°λŸ΄ & Object() μƒμ„±μž ν•¨μˆ˜ λ°©μ‹μœΌλ‘œ μƒμ„±λœ 객체의 ν”„λ‘œν† νƒ€μž… 체인

객체 λ¦¬ν„°λŸ΄ λ°©μ‹μœΌλ‘œ μƒμ„±λœ κ°μ²΄λŠ” κ²°κ΅­ λ‚΄μž₯ ν•¨μˆ˜(Built-in)인 Object() μƒμ„±μž ν•¨μˆ˜λ‘œ 객체λ₯Ό μƒμ„±ν•˜λŠ” 것을 λ‹¨μˆœν™”μ‹œν‚¨ 것이라고 μœ„μ—μ„œ μ–ΈκΈ‰ν•œ λ°” μžˆλ‹€. Object() μƒμ„±μž ν•¨μˆ˜λŠ” λ¬Όλ‘  ν•¨μˆ˜μ΄λ‹€. λ”°λΌμ„œ ν•¨μˆ˜ 객체인 Object() μƒμ„±μž ν•¨μˆ˜λŠ” 일반 객체와 달리 prototype ν”„λ‘œνΌν‹°κ°€ μžˆλ‹€.

μ•„λž˜ 좜λ ₯ κ²°κ³Όλ₯Ό 보면, 객체 λ¦¬ν„°λŸ΄μ„ μ‚¬μš©ν•˜μ—¬ 객체λ₯Ό μƒμ„±ν•œ 경우 κ·Έ 객체의 ν”„λ‘œν† νƒ€μž… κ°μ²΄λŠ” Object.prototype이닀.

let person = {
  name: 'Lee',
  gender: 'male',
  sayHello: function(){
    console.log('Hi! my name is ' + this.name);
  }
};

console.log(person.__proto__ === Object.prototype);   // β‘  true
console.log(Object.prototype.constructor === Object); // β‘‘ true

// Object() μƒμ„±μž ν•¨μˆ˜λŠ” Function κ°μ²΄λ‘œλΆ€ν„° 상속받기 λ•Œλ¬Έμ—
console.log(Object.__proto__ === Function.prototype); // β‘’ true
// Function.prototype은 Object.prototype을 μƒμ†ν•˜κ³  있기 λ•Œλ¬Έμ—
console.log(Function.prototype.__proto__ === Object.prototype); // β‘£ true

μ—¬κΈ°μ„œ 제일 ν—·κ°ˆλ¦¬λŠ” κ°œλ…μ΄ ObjectλŠ” Function κ°μ²΄λ‘œλΆ€ν„° 상속받고, Function. prototype은 Object.prototypeμœΌλ‘œλΆ€ν„° μƒμ†λ°›λŠ”λ‹€λŠ” 것이닀. πŸ€”

쑰금 ν—·κ°ˆλ¦΄ 수 μžˆλŠ”λ°, μš°μ„  Objectκ°€ Function κ°μ²΄λ‘œλΆ€ν„° μƒμ†λ°›λŠ” 것을 μ‚΄νŽ΄λ³΄μž.

ObjectλŠ” ν•¨μˆ˜ κ°μ²΄μ΄λ―€λ‘œ(Object μžμ²΄κ°€ μƒμ„±μž ν•¨μˆ˜μ΄κΈ° λ•Œλ¬Έ) 기본적으둜 Function κ°μ²΄λ‘œλΆ€ν„° 상속을 λ°›λŠ”λ‹€. λ”°λΌμ„œ Object.__proto__λŠ” Function.prototype을 가리킨닀.

Function.prototype은 ν•¨μˆ˜ κ°μ²΄λ“€μ˜ 곡톡 ν”„λ‘œν† νƒ€μž…μ„ μ œκ³΅ν•˜λŠ” 객체이닀. λͺ¨λ“  ν•¨μˆ˜ κ°μ²΄λŠ” Function.prototype을 μƒμ†ν•˜λŠ”λ°, Function.prototype μžμ²΄λŠ” Object.prototype을 μƒμ†ν•œλ‹€. 즉, Object.prototypeμ—μ„œ κΈ°λ³Έ λ©”μ„œλ“œ(toString(), hasOwnProperty() λ“±)λ₯Ό 상속받아 μ‚¬μš©ν•  수 μžˆλ‹€λŠ” λœ»μ΄λ‹€.

이 κ°œλ…μ„ 보고 Object와 Function이 μ„œλ‘œ μƒμ†ν•˜λŠ” 것이라고 ν—·κ°ˆλ¦¬λ©΄ μ•ˆλœλ‹€!! Objectκ°€ Function.prototype을 μƒμ†ν•˜κ³ , Function.prototype은 Object.prototype을 μƒμ†ν•˜λŠ” ꡬ쑰인 것이닀.


Functionκ³Ό Objectμ™€μ˜ 관계 정리

Function (ν•¨μˆ˜)
 β”œβ”€ constructor β†’ Function
 β”œβ”€ __proto__ β†’ Function.prototype
Function.prototype
 β”œβ”€ constructor β†’ Function
 β”œβ”€ __proto__ β†’ Object.prototype
Object
 β”œβ”€ constructor β†’ Function (μƒμ„±μž ν•¨μˆ˜λ‘œ μƒμ„±ν–ˆμœΌλ―€λ‘œ)
 β”œβ”€ __proto__ β†’ Function.prototype
Object.prototype
 └─ __proto__ β†’ null

🀯 이게 κ°€λŠ₯ν•œ μ΄μœ λŠ” μžλ°”μŠ€ν¬λ¦½νŠΈ 엔진이 λΆ€νŠΈμŠ€νŠΈλž© κ³Όμ •μ—μ„œ Functionκ³Ό Objectλ₯Ό λ™μ‹œμ— μ •μ˜ν•˜κ³  μ„œλ‘œλ₯Ό 연결해놓기 λ•Œλ¬Έμ΄λ‹€.

  1. Object ν•¨μˆ˜ 객체 생성
  2. Object.prototype 생성
  3. Function ν•¨μˆ˜ 객체 생성
  4. Function.prototype 생성
  5. μ„œλ‘œ μ—°κ²°
    • Object.__proto__ = Function.prototype
    • Function.__proto__ = Function.prototype
    • Function.prototype.__proto__ = Object.prototype



2. μƒμ„±μž ν•¨μˆ˜λ‘œ μƒμ„±λœ 객체의 ν”„λ‘œν† νƒ€μž… 체인

μƒμ„±μž ν•¨μˆ˜λ‘œ 객체λ₯Ό μƒμ„±ν•˜λŠ” 방식은 κ²°κ΅­ Function() μƒμ„±μž ν•¨μˆ˜λ₯Ό 톡해 ν•¨μˆ˜ 객체λ₯Ό μƒμ„±ν•œλ‹€. λ”°λΌμ„œ, μ–΄λ– ν•œ λ°©μ‹μœΌλ‘œ ν•¨μˆ˜ 객체λ₯Ό μƒμ„±ν•˜μ—¬λ„ λͺ¨λ“  ν•¨μˆ˜ 객체의 prototype κ°μ²΄λŠ” Function.prototype이닀.

function Person(name, gender) {
  this.name = name;
  this.gender = gender;
  this.sayHello = function(){
    console.log('Hi! my name is ' + this.name);
  };
}

let foo = new Person('Lee', 'male');

console.log(foo.__proto__ === Person.prototype);                // β‘  true
console.log(Person.prototype.__proto__ === Object.prototype);   // β‘‘ true
console.log(Person.prototype.constructor === Person);           // β‘’ true
console.log(Person.__proto__ === Function.prototype);           // β‘£ true
console.log(Function.prototype.__proto__ === Object.prototype); // β‘€ true

foo 객체의 ν”„λ‘œν† νƒ€μž… 객체 Person.prototype 객체와 Person() μƒμ„±μž ν•¨μˆ˜μ˜ ν”„λ‘œν† νƒ€μž… 객체인 Function.prototype의 ν”„λ‘œν† νƒ€μž… κ°μ²΄λŠ” Object.prototype객체이닀.

μ΄λŠ” 객체 λ¦¬ν„°λŸ΄ λ°©μ‹μ΄λ‚˜ μƒμ„±μž ν•¨μˆ˜ λ°©μ‹μ΄λ‚˜ 결ꡭ은 λͺ¨λ“  객체의 λΆ€λͺ¨ 객체인 Object.prototype κ°μ²΄μ—μ„œ ν”„λ‘œν† νƒ€μž… 체인이 λλ‚˜κΈ° λ•Œλ¬Έμ΄λ‹€. μ΄λ•Œ Object.prototype객체λ₯ΌΒ ν”„λ‘œν† νƒ€μž… 체인의 쒅점(End of prototype chain)이라 ν•œλ‹€. λ”°λΌμ„œ, λͺ¨λ“  κ°μ²΄λŠ” ν”„λ‘œν† νƒ€μž… 체인에 μ˜ν•΄ Object.prototype 객체의 λ©”μ†Œλ“œλ₯Ό μ‚¬μš©ν•  수 μžˆλ‹€.

0개의 λŒ“κΈ€