🌸19μž₯. ν”„λ‘œν† νƒ€μž…

πŸ‘‰ μžλ°”μŠ€ν¬λ¦½νŠΈλŠ” λͺ…λ Ήν˜•, ν•¨μˆ˜ν˜•, ν”„λ‘œν† νƒ€μž… 기반 객체지ν–₯ ν”„λ‘œκ·Έλž˜λ°μ„ μ§€μ›ν•˜λŠ” λ©€ν‹° νŒ¨λŸ¬λ‹€μž„ ν”„λ‘œκ·Έλž˜λ° 언어이닀.
  • μ›μ‹œ νƒ€μž…(primitive) 의 값을 μ œμ™Έν•œ λ‚˜λ¨Έμ§€ κ°’λ“€( ν•¨μˆ˜, λ°°μ—΄, μ •κ·œν‘œν˜„μ‹ λ“± )은 λͺ¨λ‘ 객체닀.

  • μžλ°”μŠ€ν¬λ¦½νŠΈλ§Œμ˜ ν”„λ‘œν† νƒ€μž… 기반의 객체지ν–₯ ν”„λ‘œκ·Έλž˜λ°μ΄ μ‘΄μž¬ν•œλ‹€.

βœ…19.1 객체지ν–₯ ν”„λ‘œκ·Έλž˜λ°

객체지ν–₯ ν”„λ‘œκ·Έλž˜λ°μ΄λž€, μ—¬λŸ¬ 개의 독립적 λ‹¨μœ„, 즉 **객체의 μ§‘ν•©**으둜 ν”„λ‘œκ·Έλž¨μ„ ν‘œν˜„ν•˜λ €λŠ” ν”„λ‘œκ·Έλž˜λ° νŒ¨λŸ¬λ‹€μž„

좔상화(abstraction)

  • 객체의 λ‹€μ–‘ν•œ 속성 μ€‘μ—μ„œ ν”„λ‘œκ·Έλž¨μ— ν•„μš”ν•œ μ†μ„±λ§Œ κ°„μΆ”λ € ν‘œν˜„ν•˜λŠ” 것

객체

  • μ •μ˜1. 속성을 톡해 μ—¬λŸ¬ 개의 값을 ν•˜λ‚˜μ˜ λ‹¨μœ„λ‘œ κ΅¬μ„±ν•œ 볡합적인 자료ꡬ쑰

  • μ •μ˜2. μƒνƒœ 데이터와 λ™μž‘μ„ ν•˜λ‚˜μ˜ 논리적인 λ‹¨μœ„λ‘œ 묢은 볡합적인 자료ꡬ쑰

  • κ°μ²΄λŠ” 2κ°€μ§€ μš”μ†Œλ‘œ κ΅¬μ„±λœλ‹€.

    • μƒνƒœ(state) λ₯Ό λ‚˜νƒ€λ‚΄λŠ” ν”„λ‘œνΌν‹°(property)

    • μƒνƒœλ₯Ό μ‘°μž‘ν•˜λŠ” λ™μž‘(behavior) 을 ν‘œν˜„ν•˜λŠ” λ©”μ„œλ“œ(method)

βœ…19.2 상속과 ν”„λ‘œν† νƒ€μž…

상속(inheritance) : μ–΄λ–€ 객체의 ν”„λ‘œνΌν‹°λ‚˜ λ©”μ„œλ“œλ₯Ό λ‹€λ₯Έ 객체가 상속받아 κ·ΈλŒ€λ‘œ μ‚¬μš©ν•  수 μžˆλŠ” 것

μƒμ„±μž ν•¨μˆ˜μ—μ„œ μ‚΄νŽ΄λ΄€λ“―μ΄, μƒμ„±μž ν•¨μˆ˜λŠ” λ™μΌν•œ ν”„λ‘œνΌν‹° ꡬ쑰λ₯Ό κ°–λŠ” 객체λ₯Ό μ—¬λŸ¬ 개 생성할 λ•Œ μœ μš©ν•˜λ‹€.

ν•˜μ§€λ§Œ, λ‹€μŒκ³Ό 같은 λ¬Έμ œκ°€ μžˆλ‹€.

β€˜Circle’객체 : λ°˜μ§€λ¦„, μ›μ˜ 넓이λ₯Ό κ΅¬ν•˜λŠ” λ©”μ„œλ“œλ‘œ κ΅¬μ„±λ˜μ–΄μžˆλ‹€κ³  ν•˜μž.

객체에 λŒ€ν•΄ 각각의 원은 각기 λ‹€λ₯Έ λ°˜μ§€λ¦„μ„ κ°€μ§ˆ 수 μžˆμ§€λ§Œ, μ›μ˜ 넓이λ₯Ό κ΅¬ν•˜λŠ” λ©”μ„œλ“œλŠ” λ°˜μ§€λ¦„ μ •λ³΄λ§Œ 있으면 계산은 λ™μΌν•˜λ‹€.

μƒμ„±μž ν•¨μˆ˜λ‘œ 객체λ₯Ό μ—¬λŸ¬κ°œ μƒμ„±ν•˜λ©΄, μ΄λŸ¬ν•œ λ©”μ„œλ“œλ„ κ³„μ†ν•΄μ„œ μƒμ„±ν•΄μ„œ λ¬Έμ œκ°€ 생긴닀.

β†’ μ›μ΄λΌλŠ” 객체에 λŒ€ν•΄ λ°˜μ§€λ¦„μ€ λ…λ¦½μ μœΌλ‘œ, μ›μ˜ λ°˜μ§€λ¦„μ„ 톡해 ꡬ할 수 μžˆλŠ” 정보(μ›μ˜ 넓이)λŠ” κ³΅μœ ν•˜λŠ” 것이 νš¨μœ¨μ μ΄λ‹€.

이λ₯Ό κ°€λŠ₯ν•˜λ„λ‘ ν•˜λŠ” 것이 **상속**이닀.

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

// μƒμ„±μž ν•¨μˆ˜
function Circle(radius) {
    // 각각의 원 λ°˜μ§€λ¦„ 데이터(μƒνƒœ)λŠ” 독립적
    this.radius = radius;
}

// μ›μ˜ 넓이λ₯Ό κ΅¬ν•˜λŠ” λ©”μ„œλ“œλŠ” Circle 객체의 ν”„λ‘œν† νƒ€μž…μ— λ“±λ‘ν•˜μ—¬ 곡유
// ν”„λ‘œν† νƒ€μž…μ€ Circle μƒμ„±μž ν•¨μˆ˜μ˜ prototype ν”„λ‘œν† νƒ€μž…μ— λ°”μΈλ”©λ˜μ–΄ μžˆλ‹€.
Circle.prototype.getArea = function () {
    return Math.PI * this.radius ** 2;
};

// μΈμŠ€ν„΄μŠ€ 생성
const circle1 = new Circle(1);
const circle2 = new Circle(2);

// Circle μƒμ„±μž ν•¨μˆ˜κ°€ μƒμ„±ν•œ λͺ¨λ“  μΈμŠ€ν„΄μŠ€λŠ”
// λΆ€λͺ¨ 객체 역할을 ν•˜λŠ” ν”„λ‘œν† νƒ€μž… Circle.prototypeμœΌλ‘œλΆ€ν„° λ©”μ„œλ“œλ₯Ό μƒμ†λ°›λŠ”λ‹€.
console.log(circle1.getArea === circle2.getArea); // true (Circle μƒμ„±μž ν•¨μˆ˜κ°€ μƒμ„±ν•˜λŠ” λͺ¨λ“  μΈμŠ€ν„΄μŠ€λŠ” ν•˜λ‚˜μ˜ getArea λ©”μ„œλ“œλ₯Ό κ³΅μœ ν•œλ‹€. )

console.log(circle1.getArea()); // 3.141592653589793
console.log(circle2.getArea()); // 12.566370614359172
  • μƒμ„±μž ν•¨μˆ˜κ°€ μƒμ„±ν•œ λͺ¨λ“  μΈμŠ€ν„΄μŠ€λŠ” μžμ‹ μ˜ ν”„λ‘œν† νƒ€μž…(β‡’ μƒμœ„(λΆ€λͺ¨) 객체 역할을 ν•˜λŠ” Circle.prototype)의 λͺ¨λ“  ν”„λ‘œν† νƒ€μž…κ³Ό λ©”μ„œλ“œλ₯Ό μƒμ†λ°›λŠ”λ‹€.

  • μƒμ„±μž ν•¨μˆ˜κ°€ 생성할 λͺ¨λ“  μΈμŠ€ν„΄μŠ€λŠ” λΆ€λͺ¨ 객체인 ν”„λ‘œν† νƒ€μž…μ˜ μžμ‚°μ„ κ³΅μœ ν•˜μ—¬ μ‚¬μš©ν•  수 μžˆλ‹€. λ”°λΌμ„œ, μƒμ„±μž ν•¨μˆ˜κ°€ 생성할 λͺ¨λ“  μΈμŠ€ν„΄μŠ€κ°€ κ³΅ν†΅μ μœΌλ‘œ μ‚¬μš©ν•  ν”„λ‘œνΌν‹°λ‚˜ λ©”μ„œλ“œλ₯Ό ν”„λ‘œν† νƒ€μž…μ— 미리 κ΅¬ν˜„ν•΄λ‘λ©΄ μ½”λ“œ μž¬μ‚¬μš© μΈ‘λ©΄μ—μ„œ μœ μš©ν•˜λ‹€.

βœ…19.3 ν”„λ‘œν† νƒ€μž… (객체)

λͺ¨λ“  κ°μ²΄λŠ” ν•˜λ‚˜μ˜ ν”„λ‘œν† νƒ€μž…μ„ κ°–λŠ”λ‹€.
그리고 λͺ¨λ“  ν”„λ‘œν† νƒ€μž…μ€ μƒμ„±μž ν•¨μˆ˜μ™€ μ—°κ²°λ˜μ–΄μžˆλ‹€.
  • λ”°λΌμ„œ 객체 - ν”„λ‘œν† νƒ€μž… - μƒμ„±μžν•¨μˆ˜λŠ” μ—°κ²°λ˜μ–΄ μžˆλ‹€.

    • ν”„λ‘œν† νƒ€μž…μ€ μžμ‹ μ˜ constructor ν”„λ‘œνΌν‹°λ₯Ό 톡해 μƒμ„±μž ν•¨μˆ˜μ— μ ‘κ·Όν•  수 있고, μƒμ„±μžν•¨μˆ˜λŠ” μžμ‹ μ˜ prototype ν”„λ‘œνΌν‹°λ₯Ό 톡해 ν”„λ‘œν† νƒ€μž…μ— μ ‘κ·Όν•  수 μžˆλ‹€.

  • λͺ¨λ“  κ°μ²΄λŠ” [[Prototype]]μ΄λΌλŠ” λ‚΄λΆ€ μŠ¬λ‘―μ„ κ°€μ§„λ‹€.

πŸ“Œ [[Prototype]] λ‚΄λΆ€ 슬둯

  • μžμ‹ μ˜ ν”„λ‘œν† νƒ€μž… = 객체가 μžμ‹ μ˜ [[Prototype]]을 톡해 κ°€λ¦¬ν‚€λŠ” ν”„λ‘œν† νƒ€μž…

  • [[Prototype]] λ‚΄λΆ€ 슬둯의 값은 ν”„λ‘œν† νƒ€μž…μ˜ μ°Έμ‘°λ‹€.

  • [[Prototype]]에 μ €μž₯λ˜λŠ” ν”„λ‘œν† νƒ€μž…μ€ 객체 생성 방식에 μ˜ν•΄ κ²°μ •λœλ‹€.

    • (null일 수 있음)

    • ex) 객체 λ¦¬ν„°λŸ΄({})둜 μƒμ„±λœ 객체 ν”„λ‘œν† νƒ€μž… β†’ Object.prototype

    • ex) μƒμ„±μž ν•¨μˆ˜μ— μ˜ν•΄ μƒμ„±λœ 객체 ν”„λ‘œν† νƒ€μž… β†’ μƒμ„±μž ν•¨μˆ˜μ˜ prototype ν”„λ‘œνΌν‹°μ— λ°”μΈλ”©λ˜μ–΄ μžˆλŠ” 객체

  • [[Prototype]] λ‚΄λΆ€ μŠ¬λ‘―μ—λŠ” 직접 μ ‘κ·Όν•  수 μ—†κ³  __prototype__ μ ‘κ·Όμž ν”„λ‘œνΌν‹°λ₯Ό 톡해 μžμ‹ μ˜ ν”„λ‘œν† νƒ€μž…μ— κ°„μ ‘μ μœΌλ‘œ μ ‘κ·Όν•  수 μžˆλ‹€.

__proto__ μ ‘κ·Όμž ν”„λ‘œνΌν‹°

λͺ¨λ“  κ°μ²΄λŠ” __prototype__ μ ‘κ·Όμž ν”„λ‘œνΌν‹°λ₯Ό 톡해 μžμ‹ μ˜ ν”„λ‘œν† νƒ€μž…μ— κ°„μ ‘μ μœΌλ‘œ μ ‘κ·Όν•  수 μžˆλ‹€.
  • λ‚΄λΆ€ μŠ¬λ‘―μ€ ν”„λ‘œνΌν‹°κ°€ μ•„λ‹ˆκΈ° λ•Œλ¬Έμ—, [[Prototype]] λ‚΄λΆ€ μŠ¬λ‘―μ—λ„ 직접 μ ‘κ·Όν•  수 μ—†κ³  __proto__ μ ‘κ·Όμž ν”„λ‘œνΌν‹°λ₯Ό 톡해 κ°„μ ‘μ μœΌλ‘œ μ ‘κ·Όν•  수 μžˆλ‹€.

__proto__ μ ‘κ·Όμž ν”„λ‘œνΌν‹°λŠ” 상속을 톡해 μ‚¬μš©λœλ‹€.

  • __proto__ μ ‘κ·Όμž ν”„λ‘œνΌν‹°λŠ” Object.prototype의 ν”„λ‘œνΌν‹°λ‹€.

  • λͺ¨λ“  κ°μ²΄λŠ” 상속을 톡해 Object.prototypeproto μ ‘κ·Όμž ν”„λ‘œνΌν‹°λ₯Ό μ‚¬μš©ν•  수 μžˆλ‹€.

__proto__ μ ‘κ·Όμž ν”„λ‘œνΌν‹°λ₯Ό 톡해 ν”„λ‘œν† νƒ€μž…μ— μ ‘κ·Όν•˜λŠ” 이유

  • μƒν˜Έ 참쑰에 μ˜ν•΄ ν”„λ‘œν† νƒ€μž… 체인이 μƒμ„±λ˜λŠ” 것을 λ°©μ§€ν•˜κΈ° μœ„ν•΄μ„œλ‹€.

  • μ„œλ‘œκ°€ μžμ‹ μ˜ ν”„λ‘œν† νƒ€μž…μ΄ λ˜λŠ” 비정상적인 ν”„λ‘œν† νƒ€μž… 체인 예제

    const parent = {};
    const child = {};
    
    child.__proto__ = parent;
    parent.__proto__ = child; // TypeError: Cyclic __proto__ value
  • ν”„λ‘œν† νƒ€μž… 체인은 단방ν–₯ λ§ν¬λ“œ 리슀트둜 κ΅¬ν˜„λ˜μ–΄μ•Ό ν•œλ‹€.

    • ν”„λ‘œνΌν‹° 검색 λ°©ν–₯이 ν•œμͺ½ λ°©ν–₯으둜만 ν˜λŸ¬κ°€μ•Ό ν•œλ‹€.

__proto__ μ ‘κ·Όμž ν”„λ‘œνΌν‹°λ₯Ό μ½”λ“œ λ‚΄μ—μ„œ 직접 μ‚¬μš©ν•˜λŠ” 것은 ꢌμž₯ν•˜μ§€ μ•ŠλŠ”λ‹€.

  • λͺ¨λ“  객체가 __proto__ μ ‘κ·Όμž ν”„λ‘œνΌν‹°λ₯Ό μ‚¬μš©ν•  수 μžˆλŠ” 것은 μ•„λ‹ˆκΈ° λ•Œλ¬Έμ΄λ‹€. β†’ "직접 상속"

  • λ”°λΌμ„œ, __proto__ μ ‘κ·Όμž ν”„λ‘œνΌν‹° λŒ€μ‹ 

    1. ν”„λ‘œν† νƒ€μž…μ˜ μ°Έμ‘°λ₯Ό μ·¨λ“ν•˜κ³  싢은 경우 β†’ Object.getPrototypeOf λ©”μ„œλ“œ μ‚¬μš©

    2. ν”„λ‘œν† νƒ€μž…μ„ κ΅μ²΄ν•˜κ³  싢은 경우 β†’ Object.setPrototypeOfλ©”μ„œλ“œ μ‚¬μš©

    const obj = {};
    const parent = { x: 1 };
    
    // Object.getPropertyOf λ©”μ„œλ“œλ‘œ obj 객체의 ν”„λ‘œν† νƒ€μž… 취득
    console.log(Object.getPrototypeOf(obj)); // [Object: null prototype] {}
    
    // Object.setPrototypeOf λ©”μ„œλ“œλ‘€ obj 객체의 ν”„λ‘œν† νƒ€μž…μ„ ꡐ체
    Object.setPrototypeOf(obj, parent);
    console.log(obj.__proto__); // { x: 1 }

ν•¨μˆ˜ 객체의 prototype ν”„λ‘œνΌν‹°

ν•¨μˆ˜ 객체만이 μ†Œμœ ν•˜λŠ” prototype ν”„λ‘œνΌν‹°λŠ” μƒμ„±μž ν•¨μˆ˜κ°€ 생성할 μΈμŠ€ν„΄μŠ€μ˜ ν”„λ‘œν† νƒ€μž…μ„ 가리킨닀.

  • μƒμ„±μžν•¨μˆ˜λ‘œμ„œ ν˜ΈμΆœν•  수 μ—†λŠ” ν™”μ‚΄ν‘œν•¨μˆ˜μ™€ ES6 λ©”μ„œλ“œ μΆ•μ•½ ν‘œν˜„μœΌλ‘œ μ •μ˜ν•œ λ©”μ„œλ“œλŠ” prototype ν”„λ‘œνΌν‹°λ₯Ό μ†Œμœ ν•˜μ§€ μ•Šκ³  ν”„λ‘œν† νƒ€μž…λ„ μƒμ„±ν•˜μ§€ μ•ŠλŠ”λ‹€.

    // ν•¨μˆ˜ κ°μ²΄λŠ” protoype ν”„λ‘œνΌν‹°λ₯Ό κ°€μ§„λ‹€.
    function () {}.hasOwnProperty("prototype"); // true
    
    // 일반 κ°μ²΄λŠ” prototype ν”„λ‘œνΌν‹°λ₯Ό κ°€μ§€μ§€ μ•ŠλŠ”λ‹€.
    ({}.hasOwnProperty("prototype"); // false

λͺ¨λ“  객체가 κ°€μ§€κ³  μžˆλŠ” __prototype__ μ ‘κ·Όμž ν”„λ‘œνΌν‹°μ™€ ν•¨μˆ˜ 객체만이 κ°€μ§€κ³  μžˆλŠ” prototype ν”„λ‘œνΌν‹°λŠ” λ™μΌν•œ ν”„λ‘œν† νƒ€μž…μ„ 가리킨닀.

function Person(name) {
    this.name = name;
}
const me = new Person("Kwak");

console.log(me.__proto__ === Person.prototype); // true
  • λ‹€λ§Œ μ‚¬μš©ν•˜λŠ” 주체가 λ‹€λ₯΄λ‹€.

ꡬ뢄

μ†Œμœ 

κ°’

μ‚¬μš© 주체

μ‚¬μš© λͺ©μ 

proto μ ‘κ·Όμž ν”„λ‘œνΌν‹°

λͺ¨λ“  객체

ν”„λ‘œν† νƒ€μž…μ˜ μ°Έμ‘°κ°’

λͺ¨λ“  객체

객체가 μžμ‹ μ˜ ν”„λ‘œν† νƒ€μž…μ— μ ‘κ·Ό λ˜λŠ” κ΅μ²΄ν•˜κΈ°μœ„ν•΄ μ‚¬μš©

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

constructor

ν”„λ‘œν† νƒ€μž…μ˜ μ°Έμ‘°κ°’

μƒμ„±μž ν•¨μˆ˜

μƒμ„±μž ν•¨μˆ˜κ°€ μžμ‹ μ΄ 생성할 객체(μΈμŠ€ν„΄μŠ€)의 ν”„λ‘œν† νƒ€μž…μ„ ν• λ‹Ήν•˜κΈ° μœ„ν•΄ μ‚¬μš©

ν”„λ‘œν† νƒ€μž…μ˜ constructor ν”„λ‘œνΌν‹°μ™€ μƒμ„±μž ν•¨μˆ˜

  • λͺ¨λ“  ν”„λ‘œν† νƒ€μž…μ€ constructor ν”„λ‘œνΌν‹°λ₯Ό κ°–λŠ”λ‹€.

  • constructor ν”„λ‘œνΌν‹°λŠ” prototype ν”„λ‘œνΌν‹°λ‘œ μžμ‹ μ΄ μ°Έμ‘°ν•˜κ³  μžˆλŠ” μƒμ„±μž ν•¨μˆ˜λ₯Ό 가리킨닀.

  • 이 연결은 μƒμ„±μž ν•¨μˆ˜κ°€ 생성될 λ•Œ(=ν•¨μˆ˜ 객체가 생성될 λ•Œ) 이뀄진닀.

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

const me = new Person("Kwak");

// me 객체의 μƒμ„±μž ν•¨μˆ˜λŠ” Person이닀.
console.log(me.constructor === Person); // true

πŸ“Œ μƒμ„±μž ν•¨μˆ˜μ— μ˜ν•΄ μƒμ„±λœ μΈμŠ€ν„΄μŠ€λŠ” ν”„λ‘œν† νƒ€μž…μ˜ constructor ν”„λ‘œνΌν‹°μ— μ˜ν•΄ μƒμ„±μž ν•¨μˆ˜μ™€ μ—°κ²°λœλ‹€.

Last updated