λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°
javascript/πŸ“– study

[3μ£Όμ°¨ μŠ€ν„°λ””]19μž₯-ν”„λ‘œν† νƒ€μž…

by HomieKim 2022. 2. 14.

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

  • μžλ°”μŠ€ν¬λ¦½νŠΈλŠ” λͺ…λ Ήν˜•, ν•¨μˆ˜ν˜•, ν”„λ‘œν† νƒ€μž… 기반 객체지ν–₯을 μ§€μ›ν•˜λŠ” λ©€ν‹° νŒ¨λŸ¬λ‹€μž„ ν”„λ‘œκ·Έλž˜λ° μ–Έμ–΄
  • js μ—μ„œ μ›μ‹œ νƒ€μž… 값을 μ œμ™Έν•œ λ‚˜λ¨Έμ§€ 값듀은 λͺ¨λ‘ 객체

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

  • 상속(inheritance)을 톡해 객체의 ν”„λ‘œνΌν‹°, λ©”μ„œλ“œλ₯Ό λ‹€λ₯Έ 객체가 상속받아 κ·ΈλŒ€λ‘œ μ‚¬μš©ν•  수 있게 됨.

  • JavaScriptλŠ” ν”„λ‘œν† νƒ€μž…μ„ 기반으둜 상속을 κ΅¬ν˜„ν•˜μ—¬ λΆˆν•„μš”ν•œ 쀑볡을 제거.

  • ν”„λ‘œν† νƒ€μž… μ‚¬μš©x

function Circle(radius){
this.radius = radius;
this.getArea = function () {
return Math.PI * this.radius ** 2;
};
}
const circle1 = new Circle(1);
const circle2 = new Circle(2);
console.log(circle1.getArea === circle2.getArea); // false

λ™μΌν•œ λ©”μ„œλ“œκ°€ 쀑볡 μƒμ„±λœλ‹€.

  • ν”„λ‘œν† νƒ€μž… 기반 상속 κ΅¬ν˜„
// μƒμ„±μž ν•¨μˆ˜
function Circle(radius){
this.radius = radius;
}
Circle.prototype.getArea = function() {
return Math.PI * this.radius ** 2;
}
const circle1 = new Circle(1);
const circle2 = new Circle(2);
console.log(circle1.getArea === circle2.getArea); // true

μžμ‹ μ˜ μƒνƒœλ₯Ό λ‚˜νƒ€λ‚΄λŠ” radius 만 κ°œλ³„μ μœΌλ‘œ μ†Œμœ  getAreaλ©”μ„œλ“œλ₯Ό μƒμ†λ°›μ•„μ„œ μ‚¬μš©
μ½”λ“œ μž¬μ‚¬μš©μœΌλ‘œ 쀑볡 제거

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

  • ν”„λ‘œν†  νƒ€μž… κ°μ²΄λŠ” 객체간 상속을 κ΅¬ν˜„ν•˜κΈ° μœ„ν•΄ μ‚¬μš©
  • λͺ¨λ“  κ°μ²΄λŠ” [[ Prototype ]] μ΄λΌλŠ” λ‚΄λΆ€μŠ¬λ‘― 가지고, 이 값은 객체의 생성 방식에 μ˜ν•΄ κ²°μ • 됨 (null 일 μˆ˜λ„ 있음)

    정리 : 객체가 생성될 λ•Œ 객체 생성 박식에 따라 ν”„λ‘œν†  νƒ€μž…μ΄ κ²°μ •λ˜κ³  [[ Prototype ]]에 μ €μž₯

  • λͺ¨λ“  κ°μ²΄λŠ” ν•˜λ‚˜μ˜ ν”„λ‘œν† νƒ€μž…μ„ 가짐(null 인 경우 ν”„λ‘œν†  νƒ€μž… μ—†μŒ)
  • λͺ¨λ“  ν”„λ‘œν† νƒ€μž…μ€ μƒμ„±μž ν•¨μˆ˜μ™€ μ—°κ²°λ˜μ–΄ μžˆλ‹€.

정리

  • [[ Prototype ]] 직접 μ ‘κ·Ό λΆˆκ°€, κ°μ²΄λŠ” __ proto __ μ ‘κ·Όμž ν”„λ‘œνΌν‹° μ‚¬μš©ν•˜μ—¬ μžμ‹ μ˜ [[ Prototype ]] λ‚΄λΆ€μŠ¬λ‘―μ— μ ‘κ·Ό κ°€λŠ₯
  • ν”„λ‘œν†  νƒ€μž…μ€ constructor ν”„λ‘œνΌν‹°λ₯Ό 톡해 μƒμƒμž ν•¨μˆ˜μ— μ ‘κ·Ό κ°€λŠ₯
  • μƒμ„±μž ν•¨μˆ˜λŠ” prototype ν”„λ‘œνΌν‹°λ₯Ό 톡해 ν”„λ‘œν† νƒ€μž…μ— μ ‘κ·Ό κ°€λŠ₯

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

  • μ ‘κ·Όμž ν”„λ‘œνΌν‹°λŠ” 자체적으둜 값을 가지지 μ•Šκ³  μ ‘κ·Όμž ν•¨μˆ˜λ₯Ό 제곡 (getter / setter)
const obj = {};
const parent = { x: 1 };
// getter ν•¨μˆ˜μΈ get __proto__κ°€ ν˜ΈμΆœλ˜μ–΄ obj 객체의 ν”„λ‘œν† νƒ€μž…μ„ 취득
obj.__proto__;
// setterν•¨μˆ˜μΈ set __proto__κ°€ ν˜ΈμΆœλ˜μ–΄ obj 객체의 ν”„λ‘œν† νƒ€μž…μ„ ꡐ체
obj.__proto__ = parent;
console.log(obj.x); // 1

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

  • __ proto __ μ ‘κ·Όμž ν”„λ‘œνΌν‹°λŠ” 객체가 직접 μ†Œμœ ν•˜λŠ” 것이 μ•„λ‹ˆλΌ Object.prototype의 ν”„λ‘œνΌν‹° μž…λ‹ˆλ‹€.
  • Object κ°μ²΄λŠ” μ΅œμƒμœ„ κ°μ²΄μ΄λ―€λ‘œ λͺ¨λ“  κ°μ²΄λŠ” 상속을 톡해 __ proto __ μ ‘κ·Όμž ν”„λ‘œνΌν‹°λ₯Ό μ‚¬μš© κ°€λŠ₯
const person = { name: 'Lee' };
// person κ°μ²΄λŠ” __proto__ ν”„λ‘œνΌν‹°λ₯Ό μ†Œμœ ν•˜μ§€ μ•ŠλŠ”λ‹€.
console.log(person.hasOwnProperty('__proto__')); // false
// __proto__ ν”„λ‘œνΌν‹°λŠ” λͺ¨λ“  객체의 ν”„λ‘œν† νƒ€μž… 객체인 Object.prototype의 μ ‘κ·Όμž ν”„λ‘œνΌν‹°λ‹€.
console.log(Object.getOwnPropertyDescriptor(Object.prototype, '__proto__'));
// {get: Ζ’, set: Ζ’, enumerable: false, configurable: true}
// λͺ¨λ“  κ°μ²΄λŠ” Object.prototype의 μ ‘κ·Όμž ν”„λ‘œνΌν‹° __proto__λ₯Ό 상속받아 μ‚¬μš©ν•  수 μžˆλ‹€.
console.log({}.__proto__ === Object.prototype); // true

Object.prototype

λͺ¨λ“  κ°μ²΄λŠ” ν”„λ‘œν† νƒ€μž…μ˜ 계측 ꡬ쑰인 ν”„λ‘œν† νƒ€μž… 체인에 λ¬Άμ—¬ μžˆλ‹€.
μžλ°”μŠ€ν¬λ¦½νŠΈ 엔진은 ν”„λ‘œνΌν‹°μ— μ ‘κ·Ό μ‹œ __ proto __ μ ‘κ·Όμž ν”„λ‘œνΌν‹°κ°€ κ°€λ¦¬ν‚€λŠ” μ°Έμ‘°λ₯Ό 따라 ν”„λ‘œν† νƒ€μž…μ˜ ν”„λ‘œνΌν‹°λ₯Ό 순차적으둜 검색

__ proto __ μ ‘κ·Όμž ν”„λ‘œνΌν‹°λ₯Ό 톡해 μ ‘κ·Όν•˜λŠ” 이유?

  • μƒν˜Έ 참쑰에 μ˜ν•΄ ν”„λ‘œν† νƒ€μž… 체인이 μƒμ„±λ˜λŠ” 것을 방지 ν•˜κΈ° μœ„ν•΄
  • ν”„λ‘œν†  νƒ€μž…μ€ 단방ν–₯ λ§ν¬λ“œ 리트슀둜 κ΅¬ν˜„λ˜μ–΄μ•Ό ν•œλ‹€.
  • μˆœν™˜ μ°Έμ‘°ν•˜λŠ” ν”„λ‘œν† νƒ€μž… 체인이 λ§Œλ“€μ–΄ 진닀면 ν”„λ‘œνΌν‹° 검색 μ‹œ λ¬΄ν•œ 루프

__ proto __ μ ‘κ·Όμž ν”„λ‘œνΌν‹° 직접 μ‚¬μš© ꢌμž₯ ν•˜μ§€ μ•ŠμŒ

  • 직접 상속을 톡해 Object.prototypeλ₯Ό 상속받지 μ•Šμ€ 객체λ₯Ό 생성할 μˆ˜λ„ 있음.
// objλŠ” ν”„λ‘œν† νƒ€μž… 체인의 쒅점. λ”°λΌμ„œ Object.__proto__λ₯Ό 상속받을 수 μ—†λ‹€.
const obj = Object.create(null);
// objλŠ” Object.__proto__λ₯Ό 상속받을 수 μ—†λ‹€.
console.log(obj.__proto__); // undefined
// λ”°λΌμ„œ __proto__보닀 Object.getPrototypeOf λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•˜λŠ” 편이 μ’‹λ‹€.
console.log(Object.getPrototypeOf(obj)); // null

ν”„λ‘œν† νƒ€μž… μ°Έμ‘° ν•„μš” μ‹œ : Object.getPrototypeOf μ‚¬μš©
ν”„λ‘œν† νƒ€μž… ꡐ체 ν•„μš” μ‹œ : Object.setPrototypeOf μ‚¬μš©

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

  • prototype ν”„λ‘œνΌν‹°λŠ” ν•¨μˆ˜ 객체만 가짐
  • prototype ν”„λ‘œνΌν‹°λŠ” μƒμ„±μž ν•¨μˆ˜κ°€ 생성할 μΈμŠ€ν„΄μŠ€μ˜ ν”„λ‘œν† νƒ€μž…μ„ 가리킴
  • non-constructor ν•¨μˆ˜ κ°μ²΄λŠ” prototype 가지지 μ•ŠμŒ
  • __ proto __ μ ‘κ·Όμž ν”„λ‘œνΌν‹°μ™€ ν•¨μˆ˜ 객체 만이 가지고 μžˆλŠ” prototype ν”„λ‘œνΌν‹°λŠ” κ²°κ΅­ λ™μΌν•œ ν”„λ‘œνΌνƒ€μž…μ„ 가리킨닀*
    • __ proto __
      • λͺ¨λ“  객체가 μ†Œμœ 
      • 객체가 μžμ‹μ˜ ν”„λ‘œν† νƒ€μž…μ— μ ‘κ·Ό λ˜λŠ” ꡐ체 ν•˜κΈ° μœ„ν•΄ μ‚¬μš©
    • prototype ν”„λ‘œνΌν‹°
      • constructor μ†Œμœ 
      • μƒμ„±μž ν•¨μˆ˜κ°€ μ‚¬μš© 주체
      • μƒμ„±μž ν•¨μˆ˜κ°€ μžμ‹ μ΄ 생성할 객체의 ν”„λ‘œν† νƒ€μž…μ„ ν• λ‹Ήν•˜κΈ°μœ„ν•΄ μ‚¬μš©
// μƒμ„±μž ν•¨μˆ˜
function Person(name) {
this.name = name;
}
const me = new Person('Lee');
// κ²°κ΅­ Person.prototypeκ³Ό me.__proto__λŠ” κ²°κ΅­ λ™μΌν•œ ν”„λ‘œν† νƒ€μž…μ„ 가리킨닀.
console.log(Person.prototype === me.__proto__); // true

constructor

  • λͺ¨λ“  ν”„λ‘œν† νƒ€μž…μ€ constructor ν”„λ‘œνΌν‹°λ₯Ό 가진닀.
  • constructorν”„λ‘œνΌν‹°λŠ” μžμ‹ μ„ μ°Έμ‘°ν•˜κ³  μžˆλŠ” μƒμ„±μž ν•¨μˆ˜λ₯Ό 가리림
  • ν•¨μˆ˜ 객체 (μƒμ„±μž ν•¨μˆ˜)κ°€ 생성될 λ•Œ μ—°κ²° 이루어짐
// μƒμ„±μž ν•¨μˆ˜
function Person(name) {
this.name = name;
}
const me = new Person('Lee');
// me 객체의 μƒμ„±μž ν•¨μˆ˜λŠ” Person이닀.
console.log(me.constructor === Person); // true

λ¦¬ν„°λŸ΄ ν‘œκΈ°λ²•μ— μ˜ν•΄ μƒμ„±λœ 객체의 μƒμ„±μž ν•¨μˆ˜μ™€ ν”„λ‘œν† νƒ€μž…

  • newμ—°μ‚°μžμ™€ ν•¨κ»˜ μƒμ„±μž ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜μ—¬ μΈμŠ€ν„΄μŠ€λ₯Ό μƒμ„±ν•˜λŠ” 객체 μƒμ„±ν•˜λŠ” 경우 => constructorκ°€ ν•΄λ‹Ή 객체λ₯Ό μƒμ„±ν•œ μƒμ„±μž ν•¨μˆ˜ 가리킴
  • λ¦¬ν„°λŸ΄ ν‘œκΈ°λ²•μ— μ˜ν•΄ μƒμ„±λœ 객체경우 constructorκ°€ κ°€λ¦¬ν‚€λŠ” μƒμ„±μž ν•¨μˆ˜κ°€ 객체λ₯Ό μƒμ„±ν•œ μƒμ„±μž ν•¨μˆ˜λΌκ³  단정지을 수 μ—†λ‹€.
// obj κ°μ²΄λŠ” Object μƒμ„±μž ν•¨μˆ˜λ‘œ μƒμ„±ν•œ 객체가 μ•„λ‹ˆλΌ 객체 λ¦¬ν„°λŸ΄λ‘œ μƒμ„±ν–ˆλ‹€.
const obj = {};
// ν•˜μ§€λ§Œ obj 객체의 μƒμ„±μž ν•¨μˆ˜λŠ” Object μƒμ„±μž ν•¨μˆ˜λ‹€.
console.log(obj.constructor === Object); // true
  • λ¦¬ν„°λŸ΄ ν‘œκΈ°λ²•μ— μ˜ν•΄ μƒμ„±λœ 객체도 상속을 μœ„ν•΄ ν”„λ‘œν†  νƒ€μž… ν•„μš”

    ν”„λ‘œν† νƒ€μž…μ€ μƒμ„±μž ν•¨μˆ˜μ™€ λ”λΆˆμ–΄ μƒμ„±λ˜λ©° prototype, constructor ν”„λ‘œνΌν‹°μ— μ˜ν•΄ μ—°κ²°λ˜μ–΄μžˆκΈ° λ•Œλ¬Έ

λ¦¬ν„°λŸ΄ ν‘œκΈ°λ²•μœΌλ‘œ μƒμ„±λœ κ°μ²΄λŠ” κ°€μƒμ˜ μƒμ„±μž ν•¨μˆ˜ κ°–λŠ”λ‹€.
즉, ν”„λ‘œν† νƒ€μž…κ³Ό μƒμ„±μž ν•¨μˆ˜λŠ” λ‹¨λ…μœΌλ‘œ μ‘΄μž¬ν•  수 μ—†κ³  μ–Έμ œλ‚˜ 쌍(pair)둜 쑴재

  • λ¦¬ν„°λŸ΄ ν‘œκΈ°λ²•μ— μ˜ν•΄ μƒμ„±λœ 객체의 ν”„λ‘œν† νƒ€μž…
λ¦¬ν„°λŸ΄ ν‘œκΈ°λ²• μƒμ„±μž ν•¨μˆ˜ ν”„λ‘œν† νƒ€μž…
객체 λ¦¬ν„°λŸ΄ Object Object.prototype
ν•¨μˆ˜ λ¦¬ν„°λŸ΄ Function Function.prototype
λ°°μ—΄ λ¦¬ν„°λŸ΄ Array Array.prototype
μ •κ·œ ν‘œν˜„μ‹ λ¦¬ν„°λŸ΄ RegExp RegExp.prototype

ν”„λ‘œν† νƒ€μž…μ˜ μƒμ„±μ‹œμ 

  • ν”„λ‘œν† νƒ€μž…μ€ μƒμ„±μž ν•¨μˆ˜κ°€ μƒμ„±λ˜λŠ” μ‹œμ μ— λ”λΆˆμ–΄ 생성 됨

  • μƒμ„±μž ν•¨μˆ˜λŠ” μ‚¬μš©μž μ •μ˜ μƒμ„±μž ν•¨μˆ˜μ™€ μžλ°”μŠ€ν¬λ¦½νŠΈκ°€ κΈ°λ³Έ μ œκ³΅ν•˜λŠ” 빌트인 μƒμ„±μž ν•¨μˆ˜λ‘œ ꡬ뢄할 수 μžˆλ‹€.

μ‚¬μš©μž μ •μ˜ μƒμ„±μž ν•¨μˆ˜μ™€ ν”„λ‘œν† νƒ€μž… 생성 μ‹œμ 

  • μƒμ„±μž ν•¨μˆ˜λ‘œμ„œ ν˜ΈμΆœν•  수 μžˆλŠ” ν•¨μˆ˜, 즉 constructorλŠ” ν•¨μˆ˜ μ •μ˜κ°€ ν‰κ°€λ˜μ–΄ ν•¨μˆ˜ 객체λ₯Ό μƒμ„±ν•˜λŠ” μ‹œμ μ— ν”„λ‘œν† νƒ€μž…λ„ λ”λΆˆμ–΄ 생성
  • non-constructorλŠ” ν”„λ‘œν† νƒ€μž…μ΄ μƒμ„±λ˜μ§€ μ•ŠλŠ”λ‹€.
// ν•¨μˆ˜ μ •μ˜(constructor)κ°€ ν‰κ°€λ˜μ–΄ ν•¨μˆ˜ 객체λ₯Ό μƒμ„±ν•˜λŠ” μ‹œμ μ— ν”„λ‘œν† νƒ€μž…λ„ λ”λΆˆμ–΄ μƒμ„±λœλ‹€.
console.log(Person.prototype); // {constructor: Ζ’}
// μƒμ„±μž ν•¨μˆ˜
function Person(name) {
this.name = name;
}
/* ---------------------------------------------- */
// ν™”μ‚΄ν‘œ ν•¨μˆ˜λŠ” non-constructorλ‹€.
const Person = name => {
this.name = name;
};
// non-constructorλŠ” ν”„λ‘œν† νƒ€μž…μ΄ μƒμ„±λ˜μ§€ μ•ŠλŠ”λ‹€.
console.log(Person.prototype); // undefined
  • μƒμ„±λœ ν”„λ‘œν† νƒ€μž…μ€ 였직 constructor ν”„λ‘œνΌν‹°λ§Œμ„ κ°–λŠ” 객체.

  • ν”„λ‘œν† νƒ€μž…λ„ 객체이고, λͺ¨λ“  κ°μ²΄λŠ” ν”„λ‘œν† νƒ€μž…μ„ κ°€μ§€λ―€λ‘œ ν”„λ‘œν† νƒ€μž…λ„ μžμ‹ μ˜ ν”„λ‘œν† νƒ€μž…μ„ 가짐.(Object.prototype)

빌트인 μƒμ„±μž ν•¨μˆ˜μ™€ ν”„λ‘œν† νƒ€μž… 생성 μ‹œμ 

  • λͺ¨λ“  빌트인 μƒμ„±μž ν•¨μˆ˜λŠ” μ „μ—­ 객체가 μƒμ„±λ˜λŠ” μ‹œμ μ— 생성됨
  • μƒμ„±λœ ν”„λ‘œν† νƒ€μž…μ€ 빌트인 μƒμ„±μž ν•¨μˆ˜μ˜ prototype ν”„λ‘œνΌν‹°μ— 바인딩 λœλ‹€.

μ „μ—­ 객체

  • μžλ°”μŠ€ν¬λ¦½νŠΈ 엔진에 μ˜ν•΄ μƒμ„±λ˜λŠ” νŠΉμˆ˜ν•œ 객체
  • λΈŒλΌμš°μ €μ—μ„œλŠ” window, node.js μ—μ„œλŠ” global
  • μ „μ—­κ°μ²΄λŠ” ν‘œμ€€ 빌트인 객체(Object, String, Number ...), 호슀트 객체 (webAPI ...), var ν‚€μ›Œλ“œλ‘œ μ„ μ–Έν•œ μ „μ—­λ³€μˆ˜μ™€ μ „μ—­ν•¨μˆ˜λ₯Ό ν”„λ‘œνΌν‹°λ‘œ κ°–λŠ”λ‹€.
    Math, Reflcect, JSON 을 μ œμ™Έν•œ ν‘œμ€€ 빌트인 κ°μ²΄λŠ” λͺ¨λ‘ μƒμ„±μž ν•¨μˆ˜
  • 객체가 μƒμ„±λ˜κΈ° 이전에 μƒμ„±μž ν•¨μˆ˜μ™€ ν”„λ‘œν† νƒ€μž…μ€ 이미 객체화 λ˜μ–΄ 쑴재
  • 이 ν›„ μƒμ„±μž ν•¨μˆ˜ λ˜λŠ” λ¦¬ν„°λŸ΄λ‘œ 객체λ₯Ό μƒμ„±ν•˜λ©΄ ν”„λ‘œν† νƒ€μž…μ€ μƒμ„±λœ 객체의 [[ Prototype ]] λ‚΄λΆ€ μŠ¬λ‘―μ— ν• λ‹Ήλœλ‹€.

객체 생성 방식과 ν”„λ‘œν† νƒ€μž…μ˜ κ²°μ •

  • 객체 생성방식
    1. 객체 λ¦¬ν„°λŸ΄
    2. Object μƒμ„±μž ν•¨μˆ˜
    3. μƒμ„±μž ν•¨μˆ˜
    4. Object.create λ©”μ„œλ“œ
    5. 클래슀(ES6)

객체 λ¦¬ν„°λŸ΄μ— μ˜ν•΄ μƒμ„±λœ 객체의 ν”„λ‘œν† νƒ€μž…

  • 객체 λ¦¬ν„°λŸ΄μ„ ν‰κ°€ν•˜μ—¬ 객체λ₯Ό 생성할 λ•Œ OrdinaryObjectCreate에 Object.prototype을 μ „λ‹¬ν•˜μ—¬ 연산함.
const obj = { x: 1 }; // 객체 λ¦¬ν„°λŸ΄μ΄ ν‰κ°€λ˜λ©΄μ„œ Object μƒμ„±μž ν•¨μˆ˜μ™€ Object.prototypeκ³Ό μƒμ„±λœ 객체 사이에 μ—°κ²° λ§Œλ“€μ–΄μ§
// 객체 λ¦¬ν„°λŸ΄μ— μ˜ν•΄ μƒμ„±λœ obj κ°μ²΄λŠ” Object.prototype을 상속 λ°›λŠ”λ‹€.
console.log(obj.constructor === Object); // true
console.log(obj.hasOwnProperty("x")); // true

Object μƒμ„±μž ν•¨μˆ˜μ— μ˜ν•΄ μƒμ„±λœ 객체의 ν”„λ‘œν† νƒ€μž…

  • Object μƒμ„±μž ν•¨μˆ˜μ— μ˜ν•΄ μƒμ„±λ˜λŠ” ν”„λ‘œν†  νƒ€μž…μ€ Object.prototype
  • λ¦¬ν„°λŸ΄ 생성방식과 차이점은 ν”„λ‘œνΌν‹°λ₯Ό μΆ”κ°€ν•˜λŠ” 방식
  • λ¦¬ν„°λŸ΄ 방식은 객체 λ¦¬ν„°λŸ΄ 내뢀에 ν”„λ‘œνΌν‹° μΆ”κ°€
  • Object μƒμ„±μž ν•¨μˆ˜ 방식은 빈 객체λ₯Ό μƒμ„±ν•œ 이후 ν”„λ‘œνΌν‹° μΆ”κ°€

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

  • new μ—°μ‚°μžμ™€ ν•¨κ»˜ μƒμ„±μž ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜μ—¬ μΈμŠ€ν„΄μŠ€λ₯Ό 생성할 λ•Œ OrdinaryObjectCreate에 μƒμ„±μž ν•¨μˆ˜μ˜ prototype ν”„λ‘œνΌν‹°μ— λ°”μΈλ”©λ˜μ–΄ μžˆλŠ” 객체λ₯Ό μ „λ‹¬ν•˜μ—¬ 연산함.
  • μƒμ„±μž ν•¨μˆ˜ μƒμ„±λœ ν”„λ‘œν† νƒ€μž… 객체의 ν”„λ‘œνΌν‹°λŠ” constructor뿐
  • μƒμ„±λœ ν”„λ‘œν† νƒ€μž… 객체( μƒμ„±μžν•¨μˆ˜.prototype)에 ν”„λ‘œνΌν‹°λ₯Ό μΆ”κ°€ / μ‚­μ œ ν•  수 있고 이 ν”„λ‘œνΌν‹°λŠ” μΈμŠ€ν„΄μŠ€κ°€ μƒμ†λ°›μŒ (ν”„λ‘œν† νƒ€μž… 체인에 반영)

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

  • 객체의 ν”„λ‘œνΌν‹°(λ©”μ„œλ“œ 포함)에 μ ‘κ·Όν•˜λ €κ³  ν•  λ•Œ ν•΄λ‹Ή 객체에 μ ‘κ·Όν•˜λ €λŠ” ν”„λ‘œνΌν‹°κ°€ μ—†λ‹€λ©΄, [[Prototype]] λ‚΄λΆ€ 슬둯의 μ°Έμ‘°λ₯Ό 따라 μžμ‹ μ˜ λΆ€λͺ¨ 역할을 ν•˜λŠ” ν”„λ‘œν† νƒ€μž…μ˜ ν”„λ‘œνΌν‹°λ₯Ό 순차적으둜 κ²€μƒ‰ν•˜λŠ” 것을 말함

  • ν”„λ‘œν† νƒ€μž… 체인은 μžλ°”μŠ€ν¬λ¦½νŠΈμ—μ„œ 객체지ν–₯ ν”„λ‘œκ·Έλž˜λ°μ˜ 상속을 κ΅¬ν˜„ν•˜λŠ” λ©”μ»€λ‹ˆμ¦˜

  • ν”„λ‘œν† νƒ€μž… 체인의 μ΅œμƒμœ„μ— μœ„μΉ˜ν•˜λŠ” κ°μ²΄λŠ” Object.prototype

  • 즉, λͺ¨λ“  κ°μ²΄λŠ” Object.prototype을 상속 λ°›μŒ

  • Object.prototypeμ—μ„œλ„ ν”„λ‘œνΌν‹° κ²€μƒ‰ν•˜μ§€ λͺ»ν•˜λ©΄ undefined λ°˜ν™˜

    정리
    ν”„λ‘œν† νƒ€μž… 체인 : 계측적인 ꡬ쑰의 객체의 상속과 ν”„λ‘œνΌν‹° 검색을 μœ„ν•œ λ©”μ»€λ‹ˆμ¦˜
    μŠ€μ½”ν”„ 체인 : ν•¨μˆ˜μ˜ 쀑첩 κ΄€κ³„λ‘œ 이루어진 μŠ€μ½”ν”„μ˜ 계측적 κ΅¬μ‘°μ—μ„œ μ‹λ³„μž 검색을 μœ„ν•œ λ©”μ»€λ‹ˆμ¦˜

μ˜€λ²„λΌμ΄λ”©κ³Ό ν”„λ‘œνΌν‹° μ„€λ„μž‰

  • μš©μ–΄ 정리

  • μ˜€λ²„λΌμ΄λ”©* (overriding): μƒμœ„ ν΄λž˜μŠ€κ°€ 가지고 μžˆλŠ” λ©”μ„œλ“œλ₯Ό ν•˜μœ„ ν΄λž˜μŠ€κ°€ μž¬μ •μ˜ ν•˜μ—¬ μ‚¬μš©ν•˜λŠ” 방식

  • μ˜€λ²„λ‘œλ”©*(overloading) : ν•¨μˆ˜μ΄λ¦„μ€ λ™μΌν•˜μ§€λ§Œ λ§€κ°œλ³€μˆ˜μ˜ νƒ€μž… λ˜λŠ” κ°œμˆ˜κ°€ λ‹€λ₯Έ λ©”μ„œλ“œλ₯Ό κ΅¬ν˜„ν•˜κ³ , κ΅¬λ³„ν•˜μ—¬ ν˜ΈμΆœν•˜λŠ” 방식

  • ν”„λ‘œνΌν‹° μ„€λ„μž‰*(property shadowing) : 상속 관계에 μ˜ν•΄ ν”„λ‘œνΌν‹°κ°€ κ°€λ €μ§€λŠ” ν˜„μƒ

  • μžλ°”μŠ€ν¬λ¦½νŠΈλŠ” μ˜€λ²„λ‘œλ”© 지원x, κ·ΈλŸ¬λ‚˜ arguments 객체 μ‚¬μš©ν•˜μ—¬ κ΅¬ν˜„κ°€λŠ₯

  • ν”„λ‘œν† νƒ€μž… ν”„λ‘œνΌν‹°λ₯Ό λ³€κ²½ λ˜λŠ” μ‚­μ œ ν•˜λ €λ©΄ ν•˜μœ„ 객체λ₯Ό 톡해 ν”„λ‘œν† νƒ€μž… 체인으둜 μ ‘κ·Όν•˜λŠ” 것이 μ•„λ‹ˆλΌ ν”„λ‘œν† νƒ€μž…μ— 직접 접근해야함

// ν”„λ‘œν† νƒ€μž… 체인을 톡해 ν”„λ‘œν† νƒ€μž… λ©”μ„œλ“œκ°€ μ‚­μ œλ˜μ§€ μ•ŠλŠ”λ‹€.
delete me.sayHello;
// ν”„λ‘œν† νƒ€μž… λ©”μ„œλ“œκ°€ ν˜ΈμΆœλœλ‹€.
me.sayHello(); // Hi! My name is Lee
/* ------------------------------------ */
// 직접 μ ‘κ·Όν•˜μ—¬ λ³€κ²½ / μ‚­μ œ κ°€λŠ₯
// ν”„λ‘œν† νƒ€μž… λ©”μ„œλ“œ λ³€κ²½
Person.prototype.sayHello = function () {
console.log(`Hey! My name is ${this.name}`);
};
me.sayHello(); // Hey! My name is Lee
// ν”„λ‘œν† νƒ€μž… λ©”μ„œλ“œ μ‚­μ œ
delete Person.prototype.sayHello;
me.sayHello(); // TypeError: me.sayHello is not a function

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

  • ν”„λ‘œν† νƒ€μž…μ€ μž„μ˜μ˜ λ‹€λ₯Έ 객체둜 λ³€κ²½ κ°€λŠ₯ -> λΆ€λͺ¨ 객체인 ν”„λ‘œν† νƒ€μž…μ„ λ™μ μœΌλ‘œ λ³€κ²½ κ°€λŠ₯

  • μƒμ„±μž ν•¨μˆ˜ λ˜λŠ” μΈμŠ€ν„΄μŠ€μ— μ˜ν•΄ ꡐ체가λŠ₯

  • ν”„λ‘œν† νƒ€μž…μ˜ ꡐ체λ₯Ό 톡해 상속 관계λ₯Ό λ™μ μœΌλ‘œ λ³€κ²½ν•˜λŠ” 것은 κ½€λ‚˜ λ²ˆκ±°λ‘œμš°λ―€λ‘œ, 직접 κ΅μ²΄ν•˜μ§€ μ•ŠλŠ” 것이 νŽΈλ¦¬ν•¨κ³Ό μ•ˆμ •μ„± μΈ‘λ©΄μ—μ„œ μ’‹μŒ.

instanceof μ—°μ‚°μž

객체 instanceof μƒμ„±μž ν•¨μˆ˜
  • μš°λ³€μ˜ μƒμ„±μž ν•¨μˆ˜μ˜ prototype에 λ°”μΈλ”©λœ 객체가 μ’Œλ³€μ˜ ν”„λ‘œν† νƒ€μž… 체인 상에 μ‘΄μž¬ν•˜λ©΄ true둜 ν‰κ°€λ˜κ³  μ•„λ‹Œκ²½μš° false둜 평가 됨

  • μƒμ„±μž ν•¨μˆ˜μ— μ˜ν•΄ ν”„λ‘œν† νƒ€μž…μ΄ κ΅μ²΄λ˜μ–΄λ„ μƒμ„±μž ν•¨μˆ˜μ˜ prototypeν”„λ‘œνΌν‹°μ™€ 연결은 νŒŒκ΄΄λ˜μ§€ μ•ŠμœΌλ―€λ‘œ instanceofμ—°μ‚°μžλŠ” 정상 λ™μž‘

const Person = (function () {
function Person(name) {
this.name = name;
}
// μƒμ„±μž ν•¨μˆ˜μ˜ prototype ν”„λ‘œνΌν‹°λ₯Ό 톡해 ν”„λ‘œν† νƒ€μž…μ„ ꡐ체
Person.prototype = {
sayHello() {
console.log(`Hi! My name is ${this.name}`);
}
};
return Person;
}());
const me = new Person('Lee');
// constructor ν”„λ‘œνΌν‹°μ™€ μƒμ„±μž ν•¨μˆ˜ κ°„μ˜ 연결은 νŒŒκ΄΄λ˜μ–΄λ„ instanceofλŠ” μ•„λ¬΄λŸ° 영ν–₯을 받지 μ•ŠλŠ”λ‹€.
console.log(me.constructor === Person); // false
// Person.prototype이 me 객체의 ν”„λ‘œν† νƒ€μž… 체인 상에 μ‘΄μž¬ν•˜λ―€λ‘œ true둜 ν‰κ°€λœλ‹€.
console.log(me instanceof Person); // true
// Object.prototype이 me 객체의 ν”„λ‘œν† νƒ€μž… 체인 상에 μ‘΄μž¬ν•˜λ―€λ‘œ true둜 ν‰κ°€λœλ‹€.
console.log(me instanceof Object); // true

정적 ν”„λ‘œνΌν‹°/λ©”μ„œλ“œ

  • 정적(static) ν”„λ‘œνΌν‹° / λ©”μ„œλ“œλŠ” μƒμ„±μž ν•¨μˆ˜λ‘œ μΈμŠ€ν„΄μŠ€λ₯Ό μƒμ„±ν•˜μ§€ μ•Šμ•„λ„ μ°Έμ‘° / 호좜 ν•  수 μžˆλŠ” ν”„λ‘œνΌν‹° λ©”μ„œλ“œλ₯Ό λ§ν•œλ‹€.

  • 정적 ν”„λ‘œνΌν‹°/λ©”μ„œλ“œλŠ” μƒμ„±μž ν•¨μˆ˜κ°€ μƒμ„±ν•œ μΈμŠ€ν„΄μŠ€λ‘œ μ°Έμ‘°/ν˜ΈμΆœν•  수 μ—†μŒ.

  • 정적 ν”„λ‘œνΌν‹°/λ©”μ„œλ“œλŠ” μΈμŠ€ν„΄μŠ€μ˜ ν”„λ‘œν† νƒ€μž… 체인에 μ†ν•œ ν”„λ‘œνΌν‹°/λ©”μ„œλ“œκ°€ μ•„λ‹ˆλ―€λ‘œ μΈμŠ€ν„΄μŠ€λ‘œ μ ‘κ·Όν•  수 μ—†μŒ.

  • μΈμŠ€ν„΄μŠ€/ν”„λ‘œν† νƒ€μž… λ©”μ„œλ“œ λ‚΄μ—μ„œ thisλ₯Ό μ‚¬μš©ν•˜μ§€ μ•ŠλŠ”λ‹€λ©΄ 정적 λ©”μ„œλ“œλ‘œ 변경해도 λ¬΄λ°©ν•˜λ‹€.

ν”„λ‘œνΌν‹° 쑴재 확인

inμ—°μ‚°μž

  • inμ—°μ‚°μžλŠ” 객체 내에 νŠΉμ • ν”„λ‘œνΌν‹°κ°€ μ‘΄μž¬ν•˜λŠ”μ§€ μ—¬λΆ€λ₯Ό ν™•μΈν•œλ‹€.
/**
* key: ν”„λ‘œνΌν‹° ν‚€λ₯Ό λ‚˜νƒ€λ‚΄λŠ” λ¬Έμžμ—΄
* object: 객체둜 ν‰κ°€λ˜λŠ” ν‘œν˜„μ‹
*/
key in object
  • in μ—°μ‚°μžλŠ” 객체의 ν”„λ‘œνΌν‹° λΏλ§Œμ•„λ‹ˆλΌ 객체가 상속받은 λͺ¨λ“  ν”„λ‘œν† νƒ€μž…μ˜ ν”„λ‘œνΌν‹°λ₯Ό ν™•μΈν•œλ‹€. (Object.prototypeμ—μ„œ 상속받은 것도 true둜 νŒλ‹¨)
console.log('toString' in person); // true

Object.prototype.hasOwnProperty λ©”μ„œλ“œ

  • 객체 고유의 ν”„λ‘œνΌν‹°(상속 받은 ν”„λ‘œν† νƒ€μž… μ œμ™Έ)만 ν™•μΈν•˜λŠ” 방법.
console.log(person.hasOwnProperty('toString')); // false

ν”„λ‘œνΌν‹° μ—΄κ±°

for ... in λ¬Έ

/*
key: propertyλ₯Ό ν• λ‹Ή 받을 λ³€μˆ˜
object: μ—΄κ±°ν•  객체
*/
for (const key in object) { ... }
  • ν”„λ‘œνΌν‹°μ˜ 개수만큼 μˆœνšŒν•˜μ—¬ λ³€μˆ˜ μ„ μ–Έλ¬Έ(key)μ—μ„œ μ„ μ–Έν•œ λ³€μˆ˜μ— ν”„λ‘œνΌν‹° ν‚€λ₯Ό ν• λ‹Ή.

  • 순회 λŒ€μƒμ˜ 객체 ν”„λ‘œνΌν‹° 뿐만 μ•„λ‹ˆλΌ 상속받은 ν”„λ‘œν† νƒ€μž…μ˜ ν”„λ‘œνΌν‹°κΉŒμ§€ μ—΄κ±°

  • [[Enumerable]]의 값이 false이면 μ—΄κ±°ν•˜μ§€ μ•ŠμŒ.

  • ν‚€κ°€ μ‹¬λ²ŒμΈ ν”„λ‘œνΌν‹° λ˜ν•œ μ—΄κ±°ν•˜μ§€ μ•ŠμŒ.

  • λŒ€λΆ€λΆ„μ˜ λͺ¨λ˜ λΈŒλΌμš°μ €λŠ” μˆœμ„œλ₯Ό 보μž₯ν•˜κ³  숫자(사싀은 λ¬Έμžμ—΄)인 ν”„λ‘œνΌν‹° 킀에 λŒ€ν•΄μ„œλŠ” 정렬을 μ‹€μ‹œν•˜μ§€λ§Œ, μ›λž˜ for ... in 문은 μˆœμ„œλ₯Ό 보μž₯ν•˜μ§€ μ•ŠμœΌλ―€λ‘œ 주의.

  • λ°°μ—΄μ—λŠ” for ... in이 μ•„λ‹Œ for, for ... of, Array.prototype.forEach λ“±μ˜ λ©”μ„œλ“œ ꢌμž₯.

// 상속받을 ν”„λ‘œνΌν‹°λŠ” μ œμ™Έν•˜κ³  객체 μžμ‹ μ˜ ν”„λ‘œνΌν‹°λ§Œ μ—΄κ±°ν•˜λŠ” 방법
const person = {
name: 'Lee',
address: 'Seoul',
__proto__: { age: 20 }
};
for (const key in person) {
// 객체 μžμ‹ μ˜ ν”„λ‘œνΌν‹°μΈμ§€ ν™•μΈν•œλ‹€.
if (!person.hasOwnProperty(key)) continue;
console.log(key + ': ' + person[key]);
}
// name: Lee
// address: Seoul

ν”„λ‘œν† νƒ€μž… 체인 상에 μ‘΄μž¬ν•˜λŠ” λͺ¨λ“  ν”„λ‘œν† νƒ€μž…μ˜ ν”„λ‘œνΌν‹° μ€‘μ—μ„œ ν”„λ‘œνΌν‹° μ–΄νŠΈλ¦¬λ·°νŠΈ [[Enumerable]]의 값이 true인 ν”„λ‘œνΌν‹°λ₯Ό μˆœνšŒν•˜λ©° μ—΄κ±°ν•˜λŠ” 방법.

Object.keys/values/entries λ©”μ„œλ“œ

  • Object.keys: 객체 μžμ‹ μ˜ μ—΄κ±° κ°€λŠ₯ν•œ ν”„λ‘œνΌν‹° ν‚€λ₯Ό λ°°μ—΄λ‘œ λ°˜ν™˜.

  • Object.values: 객체 μžμ‹ μ˜ μ—΄κ±° κ°€λŠ₯ν•œ ν”„λ‘œνΌν‹° 값을 λ°°μ—΄λ‘œ λ°˜ν™˜.

  • Object.entries: 객체 μžμ‹ μ˜ μ—΄κ±° κ°€λŠ₯ν•œ ν”„λ‘œνΌν‹° 킀와 κ°’μ˜ 쌍의 배열을 λ°°μ—΄λ‘œ λ°˜ν™˜.

객체 μžμ‹  고유의 ν”„λ‘œνΌν‹° μ€‘μ—μ„œ ν”„λ‘œνΌν‹° μ–΄νŠΈλ¦¬λ·°νŠΈ [[Enumerable]]의 값이 true인 μ—΄κ±°ν•˜λŠ” 방법.

λŒ“κΈ€