[πŸ“– λͺ¨λ˜ μžλ°”μŠ€ν¬λ¦½νŠΈ λ”₯λ‹€μ΄λΈŒ] 19μž₯. ν”„λ‘œν† νƒ€μž… - 1

λ…Έμ˜μ™„Β·2023λ…„ 11μ›” 6일
0

JavaScript(Deep Dive)

λͺ©λ‘ 보기
14/23
post-thumbnail
post-custom-banner

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

  • μžλ°”μŠ€ν¬λ¦½νŠΈλŠ” λͺ…λ Ήν˜• ν•¨μˆ˜ν˜• ν”„λ‘œν† νƒ€μž… 기반 객체 지ν–₯ ν”„λ‘œκ·Έλž˜λ°μ„ μ§€μ›ν•˜λŠ” λ©€ν‹° νŒ¨λŸ¬λ‹€μž„ ν”„λ‘œκ·Έλž˜λ° μ–Έμ–΄λ‹€.
  • μžλ°”μŠ€ν¬λ¦½νŠΈλŠ” 객체 기반의 ν”„λ‘œκ·Έλž˜λ° 언어이며 μžλ°”μŠ€ν¬λ¦½νŠΈλ₯Ό 이루고 μžˆλŠ” 거의 "λͺ¨λ“  것"이 객체닀.

1. 객체지ν–₯ ν”„λ‘œκ·Έλž˜λ°

객체지ν–₯ ν”„λ‘œκ·Έλž˜λ°μ€ ν”„λ‘œκ·Έλž¨μ„ λͺ…λ Ήμ–΄ λ˜λŠ” ν•¨μˆ˜μ˜ λͺ©λ‘μœΌλ‘œ λ³΄λŠ” 전톡적인 λͺ…λ Ήν˜• ν”„λ‘œκ·Έλž˜λ°μ˜ μ ˆμ°¨μ§€ν–₯적 κ΄€μ μ—μ„œ λ²—μ–΄λ‚˜ μ—¬λŸ¬κ°œμ˜ 독립적 λ‹¨μœ„ 즉, 객체의 μ§‘ν•©μœΌλ‘œ ν”„λ‘œκ·Έλž¨μ„ ν‘œν˜„ν• λ €λŠ” ν”„λ‘œκ·Έλž˜λ° νŒ¨λŸ¬λ‹€μž„μ„ λ§ν•œλ‹€.

객체지ν–₯ ν”„λ‘œκ·Έλž˜λ°μ€ μ‹€μ„Έκ³„μ˜ 싀체(μ‚¬λ¬Όμ΄λ‚˜ κ°œλ…)λ₯Ό μΈμ‹ν•˜λŠ” 철학적 사고λ₯Ό ν”„λ‘œκ·Έλž˜λ°μ— μ ‘λͺ©ν•˜λ €λŠ” μ‹œλ„μ—μ„œ μ‹œμž‘

μ‹€μ²΄λŠ” νŠΉμ„±μ΄λ‚˜ μ„±μ§ˆμ„ λ‚˜νƒ€λ‚΄λŠ” 속성을 가지고 있고, 이λ₯Ό 톡해 싀체λ₯Ό μΈμ‹ν•˜κ±°λ‚˜ ꡬ별. ex) μ‚¬λžŒμ€ "이름", "μ£Όμ†Œ", "성별", "λ‚˜μ΄", "μ‹ μž₯", "체쀑", "ν•™λ ₯" λ“± λ‹€μ–‘ν•œ 속성을 가지고 있고, μ΄λ•Œ 이름이 이무개 성별 μ—¬μ„± λ‚˜μ΄ 20세인 μ‚¬λžŒκ³Ό 같이 속성을 ꡬ체적으둜 ν‘œν˜„ν•˜λ©΄ νŠΉμ •ν•œ μ‚¬λžŒμ„ λ‹€λ₯Έ μ‚¬λžŒκ³Ό κ΅¬λ³„ν•˜μ—¬ 인식할 수 μžˆλ‹€

μ‚¬λžŒμ—κ²ŒλŠ” λ‹€μ–‘ν•œ 속성이 μžˆμœΌλ‚˜ μš°λ¦¬κ°€ κ΅¬ν˜„ν•˜λ €λŠ” ν”„λ‘œκ·Έλž¨μ—μ„œλŠ” μ‚¬λžŒμ˜ "이름", "μ£Όμ†Œ"λΌλŠ” μ†μ„±μ—λ§Œ κ΄€μ‹¬μžˆλ‹€κ³  κ°€μ • 이처럼 λ‹€μ–‘ν•œ 속성 쀑에 ν”„λ‘œκ·Έλž¨μ— ν•„μš”ν•œ μ†μ„±λ§Œ κ°„μ£Όλ € λ‚΄μ—¬ ν‘œν˜„ν•˜λ €λŠ” 것을 좔상화라 ν•œλ‹€.

// 이름과 μ£Όμ†Œ 속성을 κ°–λŠ” 객체
const person = {
  	name: "noh",
  	address: "Seoul"
};

console.log(person); // {name: "noh", address: "Seoul"}

μœ„μ˜ person 객체λ₯Ό λ‹€λ₯Έ 객체와 κ΅¬λ³„ν•˜μ—¬ 인식할 수 μžˆλ‹€. 이처럼 속성을 톡해 μ—¬λŸ¬ 개의 값을 ν•˜λ‚˜μ˜ λ‹¨μœ„λ‘œ κ΅¬μ„±ν•œ 볡합적인 자료ꡬ쑰λ₯Ό κ°μ²΄λΌν•˜λ©°, 객체지ν–₯ ν”„λ‘œκ·Έλž˜λ°μ€ 독립적인 객체의 μ§‘ν•©μœΌλ‘œ ν”„λ‘œκ·Έλž¨μ„ ν‘œν˜„ν•˜λ €λŠ” ν”„λ‘œκ·Έλž˜λ° νŒ¨λŸ¬λ‹€μž„μ΄λ‹€.

μ΄λ²ˆμ—λŠ” μ›μ΄λΌλŠ” κ°œλ…μ„ 객체둜 λ§Œλ“€μ–΄λ³΄μž. μ›μ—λŠ” λ°˜μ§€λ¦„μ΄λΌλŠ” 속성이 있고 이 λ°˜μ§€λ¦„μ„ 가지고 지름, λ‘˜λ ˆ, 넓이λ₯Ό ꡬ할 수 μžˆλ‹€. μ΄λ•Œ λ°˜μ§€λ¦„μ€ μ›μ˜ μƒνƒœλ₯Ό λ‚˜νƒ€λ‚΄λŠ” 데이터이며 μ›μ˜ 지름, λ‘˜λ ˆ, 넓이λ₯Ό κ΅¬ν•˜λŠ” 것은 λ™μž‘μ΄λ‹€.

const circle = {
  // property
  radius: 5, // λ°˜μ§€λ¦„

  // method
  // μ›μ˜ 지름: 2r
  getDiameter() {
    return 2 * this.radius;
  },

  // method
  // μ›μ˜ λ‘˜λ ˆ: 2Ο€r
  getPerimeter() {
    return 2 * Math.PI * this.radius;
  },

  // method
  // μ›μ˜ 넓이: Ο€rr
  getArea() {
    return Math.PI * this.radius ** 2;
  }
};

console.log(circle);
// {radius: 5, getDiameter: Ζ’, getPerimeter: Ζ’, getArea: Ζ’}

console.log(circle.getDiameter());  // 10
console.log(circle.getPerimeter()); // 31.41592653589793
console.log(circle.getArea());      // 78.53981633974483

객체지ν–₯ ν”„λ‘œκ·Έλž˜λ°μ€ 객체의 μƒνƒœλ₯Ό λ‚˜νƒ€λ‚΄λŠ” 데이터와 μƒνƒœ 데이터λ₯Ό μ‘°μž‘ν•  수 μžˆλŠ” λ™μž‘μ„ ν•˜λ‚˜μ˜ 논리적인 λ‹¨μœ„λ‘œ λ¬Άμ–΄ μƒκ°ν•œλ‹€. λ”°λΌμ„œ κ°μ²΄λŠ” μƒνƒœ 데이터와 λ™μž‘μ„ ν•˜λ‚˜μ˜ 논리적인 λ‹¨μœ„λ‘œ 묢은 볡합적인 자료ꡬ쑰라고 ν•  수 μžˆλ‹€. μ΄λ•Œ 객체의 μƒνƒœ 데이터λ₯Ό ν”„λ‘œνΌν‹° λ™μž‘μ„ λ©”μ„œλ“œλΌ λΆ€λ₯Έλ‹€

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

상속은 객체지ν–₯ ν”„λ‘œκ·Έλž˜λ°μ˜ 핡심 κ°œλ…μœΌλ‘œ, μ–΄λ–€ 객체의 ν”„λ‘œνΌν‹° λ˜λŠ” λ©”μ„œλ“œλ₯Ό λ‹€λ₯Έ 객체가 상속받아 κ·ΈλŒ€λ‘œ μ‚¬μš©ν•  수 μžˆλŠ” 것을 λ§ν•œλ‹€. μžλ°”μŠ€ν¬λ¦½νŠΈλŠ” ν”„λ‘œν† νƒ€μž…μ„ 기반으둜 상속을 κ΅¬ν˜„ν•˜μ—¬ λΆˆν•„μš”ν•œ 쀑볡을 μ œκ±°ν•œλ‹€.

πŸ‘‰ λ©”μ„œλ“œλ₯Ό μ€‘λ³΅μœΌλ‘œ 생성 μ†Œμœ ν•˜λŠ” 예제

// μƒμ„±μž ν•¨μˆ˜
function Circle(radius) {
  this.radius = radius;
  this.getArea = function () {
    // Math.PIλŠ” μ›μ£Όμœ¨μ„ λ‚˜νƒ€λ‚΄λŠ” μƒμˆ˜λ‹€.
    return Math.PI * this.radius ** 2;
  };
}

// λ°˜μ§€λ¦„μ΄ 1인 μΈμŠ€ν„΄μŠ€ 생성
const circle1 = new Circle(1);
// λ°˜μ§€λ¦„μ΄ 2인 μΈμŠ€ν„΄μŠ€ 생성
const circle2 = new Circle(2);

// Circle μƒμ„±μž ν•¨μˆ˜λŠ” μΈμŠ€ν„΄μŠ€λ₯Ό 생성할 λ•Œλ§ˆλ‹€ λ™μΌν•œ λ™μž‘μ„ ν•˜λŠ”
// getArea λ©”μ„œλ“œλ₯Ό 쀑볡 μƒμ„±ν•˜κ³  λͺ¨λ“  μΈμŠ€ν„΄μŠ€κ°€ 쀑볡 μ†Œμœ ν•œλ‹€.
// getArea λ©”μ„œλ“œλŠ” ν•˜λ‚˜λ§Œ μƒμ„±ν•˜μ—¬ λͺ¨λ“  μΈμŠ€ν„΄μŠ€κ°€ κ³΅μœ ν•΄μ„œ μ‚¬μš©ν•˜λŠ” 것이 λ°”λžŒμ§ν•˜λ‹€.
console.log(circle1.getArea === circle2.getArea); // false

console.log(circle1.getArea()); // 3.141592653589793
console.log(circle2.getArea()); // 12.566370614359172

Circle μƒμ„±μž ν•¨μˆ˜κ°€ μƒμ„±ν•˜λŠ” λͺ¨λ“  객체(μΈμŠ€ν„΄μŠ€κ°€)λŠ” radius ν”„λ‘œνΌν‹° getArea λ©”μ„œλ“œλ₯Ό κ°–λŠ”λ‹€.

radius ν”„λ‘œνΌν‹° 값은 일반적으둜 μΈμŠ€ν„΄μŠ€ λ§ˆλ‹€ λ‹€λ₯΄λ‹€μ§€λ§Œ getArea λ©”μ„œλ“œλŠ” λͺ¨λ“  μΈμŠ€ν„΄μŠ€κ°€ λ™μΌν•œ λ‚΄μš©μ˜ λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•˜λ―€λ‘œ 단 ν•˜λ‚˜λ§Œ μƒμ„±ν•˜μ—¬ λͺ¨λ“  μΈμŠ€ν„΄μŠ€κ°€ κ³΅μœ ν•΄μ„œ μ‚¬μš©ν•˜λŠ” 것이 λ°”λžŒμ§ν•˜λ‹€.

πŸ‘‰ ν”„λ‘œν† νƒ€μž…μ„ 기반으둜 상속을 κ΅¬ν˜„ν•œ 예제

// μƒμ„±μž ν•¨μˆ˜
function Circle(radius) {
  this.radius = radius;
}

// Circle μƒμ„±μž ν•¨μˆ˜κ°€ μƒμ„±ν•œ λͺ¨λ“  μΈμŠ€ν„΄μŠ€κ°€ getArea λ©”μ„œλ“œλ₯Ό
// κ³΅μœ ν•΄μ„œ μ‚¬μš©ν•  수 μžˆλ„λ‘ ν”„λ‘œν† νƒ€μž…μ— μΆ”κ°€ν•œλ‹€.
// ν”„λ‘œν† νƒ€μž…μ€ 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μœΌλ‘œλΆ€ν„° getArea λ©”μ„œλ“œλ₯Ό μƒμ†λ°›λŠ”λ‹€.
// 즉, Circle μƒμ„±μž ν•¨μˆ˜κ°€ μƒμ„±ν•˜λŠ” λͺ¨λ“  μΈμŠ€ν„΄μŠ€λŠ” ν•˜λ‚˜μ˜ getArea λ©”μ„œλ“œλ₯Ό κ³΅μœ ν•œλ‹€.
console.log(circle1.getArea === circle2.getArea); // true

console.log(circle1.getArea()); // 3.141592653589793
console.log(circle2.getArea()); // 12.566370614359172

μžλ°”μŠ€ν¬λ¦½νŠΈλŠ” ν”„λ‘œν† νƒ€μž…μ„ 기반으둜 상속을 κ΅¬ν˜„ν•œλ‹€. Circle μƒμ„±μž ν•¨μˆ˜κ°€ μƒμ„±ν•œ λͺ¨λ“  μΈμŠ€ν„΄μŠ€ μžμ‹ μ˜ ν”„λ‘œν† νƒ€μž…, 즉 μƒμœ„(λΆ€λͺ¨) 객체 역할을 ν•˜λŠ” Circle.prototype의 λͺ¨λ“  ν”„λ‘œνΌν‹°μ™€ λ©”μ„œλ“œλ₯Ό μƒμ†λ°›λŠ”λ‹€.

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

ν”„λ‘œν† νƒ€μž… κ°μ²΄λž€ 객체지ν–₯ ν”„λ‘œκ·Έλž˜λ°μ˜ 근간을 μ΄λ£¨λŠ” 객체간 상속을 κ΅¬ν˜„ν•˜κΈ° μœ„ν•΄ μ‚¬μš©.

ν”„λ‘œν† νƒ€μž…μ€ μ–΄λ–€ 객체의 μƒμœ„(λΆ€λͺ¨) 객체의 역할을 ν•˜λŠ” κ°μ²΄λ‘œμ„œ λ‹€λ₯Έ 객체에 곡유 ν”„λ‘œνΌν‹°(λ©”μ„œλ“œ 포함)λ₯Ό μ œκ³΅ν•œλ‹€. ν”„λ‘œν† νƒ€μž…μ„ 상속받은 ν•˜μœ„(μžμ‹) κ°μ²΄λŠ” μƒμœ„ 객체의 ν”„λ‘œνΌν‹°λ₯Ό μžμ‹ μ˜ ν”„λ‘œνΌν‹°μ²˜λŸΌ 자유둭게 μ‚¬μš©ν•  수 μžˆλ‹€.

λͺ¨λ“  κ°μ²΄λŠ” [[Prototype]]μ΄λΌλŠ” λ‚΄λΆ€ μŠ¬λ‘―μ„ 가지며, 이 λ‚΄λΆ€ 슬둯의 값은 ν”„λ‘œν† νƒ€μž…μ˜ μ°Έμ‘°λ‹€. [[Prototype]]에 μ €μž₯λ˜λŠ” ν”„λ‘œν† νƒ€μž…μ€ 객체 생성 방식에 μ˜ν•΄ κ²°μ •λœλ‹€. 즉, 객체가 μƒμ„±λ λ•Œ 객체 생성방식에 따라 ν”„λ‘œν† νƒ€μž…μ΄ κ²°μ •λ˜κ³  [[Prototype]]에 μ €μž₯λœλ‹€. ex) 객체 λ¦¬ν„°λŸ΄μ— μ˜ν•΄ μƒμ„±λœ 객체의 ν”„λ‘œν† νƒ€μž…μ€ Object.prototype이고 μƒμ„±μž ν•¨μˆ˜μ— μ˜ν•΄ μƒμ„±λœ 객체의 ν”„λ‘œν† νƒ€μž…μ€ μƒμ„±μž ν•¨μˆ˜μ˜ prototype ν”„λ‘œνΌν‹°μ— 바인딩 λ˜μ–΄ μžˆλŠ” 객체닀.

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

[[Prototype]] λ‚΄λΆ€ μŠ¬λ‘―μ—λŠ” 직접 μ ‘κ·Όν•  수 μ—†μ§€λ§Œ, μœ„ 그림처럼 __proto__ μ ‘κ·Όμž ν”„λ‘œνΌν‹°λ₯Ό 톡해 μžμ‹ μ˜ ν”„λ‘œνΌν‹°μ— μ ‘κ·Όν•  수 μžˆλ‹€.

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

βœ” μƒμ„±μž ν•¨μˆ˜ 객체의 [[Prototype]]

βœ” 일반 객체의 [[Prototype]]

βœ” μƒμ„±μž ν•¨μˆ˜λ‘œ μƒμ„±λœ 객체의 [[Prototype]]

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

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

πŸ’‘ __proto__λŠ” μ ‘κ·Όμž ν”„λ‘œνΌν‹°λ‹€.

16.3.2 절의 μ ‘κ·Όμž ν”„λ‘œνΌν‹°μ—μ„œ μ‚΄νŽ΄λ³Έ 것 처럼 μ ‘κ·Όμž ν”„λ‘œνΌν‹°λŠ” μžμ²΄μ μœΌλ‘œλŠ” κ°’[[Value]]을 갖지 μ•Šκ³ , μ ‘κ·Όμž ν•¨μˆ˜ [[Get]] [[Set]] ν”„λ‘œνΌν‹° μ–΄νŠΈλ¦¬λ·°νŠΈλ‘œ κ΅¬μ„±λœ ν”„λ‘œνΌν‹°λ‹€.

const obj = {};
const parent = { x : 1 };

// getter ν•¨μˆ˜μΈ get __proto__κ°€ ν˜ΈμΆœλ˜μ–΄ obj 객체의 ν”„λ‘œν† νƒ€μž…μ„ 취득
obj.__proto__;

// setter ν•¨μˆ˜μΈ set __proto__κ°€ ν˜ΈμΆœλ˜μ–΄ obj 객체의 ν”„λ‘œν† νƒ€μž…μ„ ꡐ체
obj.__proto__ = parent;

console.log(obj.x_;

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

__proto__ μ ‘κ·Όμž ν”„λ‘œνΌν‹°λŠ” 객체가 직접 μ†Œμœ ν•˜λŠ” ν”„λ‘œνΌν‹°κ°€ μ•„λ‹ˆλΌ Object.prototype의 ν”„λ‘œνΌν‹°μ΄λ‹€. λͺ¨λ“  κ°μ²΄λŠ” 상속을 톡해 Object.prototype.__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

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

[[Prototype]] λ‚΄λΆ€ 슬둯의 κ°’, 즉 ν”„λ‘œν† νƒ€μž…μ— μ ‘κ·Όν•˜κΈ° μœ„ν•΄ μ ‘κ·Όμž ν”„λ‘œνΌν‹°λ₯Ό μ‚¬μš©ν•˜λŠ” μ΄μœ λŠ” μƒν˜Έ 참쑰에 μ˜ν•΄ ν”„λ‘œν† νƒ€μž… 체인이 μƒμ„±λ˜λŠ” 것을 λ°©μ§€ν•˜κΈ° μœ„ν•΄μ„œμ΄λ‹€.

const parent = {};
const child = {};

// child ν”„λ‘œν† νƒ€μž…μ„ parent둜 μ„€μ •
child.__proto__ = parent;
// parent ν”„λ‘œν† νƒ€μž…μ„ child둜 μ„€μ •
parent.__proto__ = child; // TypeError: Cyclic __proto__ value

λ‹¨λ°˜ν–₯ λ§ν¬λ“œ 리슀트둜 κ΅¬ν˜„λ˜μ–΄μ•Ό ν•œλ‹€. 즉, ν”„λ‘œνΌν‹° 검색 λ°©ν–₯이 ν•œμͺ½λ°©ν–₯으둜 ν˜λŸ¬κ°€μ•Όν•œλ‹€. ν•˜μ§€λ§Œ μœ„ μ˜ˆμ œλŠ” μ„œλ‘œκ°€ μ„œλ‘œλ₯Ό ν”„λ‘œν† νƒ€μž…μ΄ λ˜λŠ” 비정상적인 경우, λ‹€μ‹œλ§ν•΄ μˆœν™˜ μ°Έμ‘°κ°€ λ§Œλ“€μ–΄μ Έμ„œλŠ” μ•ˆλœλ‹€.

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

__proto__ μ ‘κ·Όμž ν”„λ‘œνΌν‹°λŠ” ES5κΉŒμ§€ ECMAScript 사양에 ν¬ν•¨λ˜μ§€ μ•Šμ€ λΉ„ν‘œμ€€μ΄μ—ˆλ‹€. ν•˜μ§€λ§Œ 일뢀 λΈŒλΌμš°μ €μ—μ„œ __proto__λ₯Ό 지원 λΈŒλΌμš°μ € ν˜Έν™˜μ„±μ„ κ³ λ €ν•˜μ—¬ ES6μ—μ„œ __proto__λ₯Ό ν‘œμ€€μœΌλ‘œ μ±„νƒν–ˆλ‹€.

ν•˜μ§€λ§Œ μ½”λ“œ λ‚΄μ—μ„œ __proto__ μ ‘κ·Όμž ν”„λ‘œνΌν‹°λ₯Ό 직접 μ‚¬μš©ν•˜λŠ” 것은 ꢌμž₯ν•˜μ§€ μ•ŠλŠ”λ‹€. λͺ¨λ“  객체가 __proto__ μ ‘κ·Όμž ν”„λ‘œνΌν‹°λ₯Ό μ‚¬μš©ν•  수 μžˆλŠ” 것은 μ•„λ‹ˆκΈ° λ•Œλ¬Έμ΄λ‹€. 직접 상속을 톡해 Object.prototype을 상속받지 μ•ŠλŠ” 객체λ₯Ό 생성할 μˆ˜λ„ 있기 λ•Œλ¬Έμ— __proto__ μ ‘κ·Όμžν”„λ‘œνΌν‹°λ₯Ό μ‚¬μš©ν•  수 μ—†λŠ” κ²½μš°κ°€ μžˆλ‹€.

// 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

λ”°λΌμ„œ __proto__ μ ‘κ·Όμž ν”„λ‘œνΌν‹° λŒ€μ‹  ν”„λ‘œν† νƒ€μž…μ˜ μ°Έμ‘°λ₯Ό μ·¨λ“ν•˜κ³  싢은 κ²½μš°μ—λŠ” Object.getPrototypeOf λ©”μ„œλ“œλ₯Ό μ‚¬μš©, ν”„λ‘œν† νƒ€μž…μ„ κ΅μ²΄ν•˜κ³  싢은 κ²½μš°μ—λŠ” Object.setPrototypeOf λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•  것을 ꢌμž₯.

const obj = {};
const parent = { x : 1 };

// obj 객체의 ν”„λ‘œν† νƒ€μž…μ„ 취득
Object.getPrototypeOf(obj); // obj.__proto__;
// obj 객체의 ν”„λ‘œν† νƒ€μž…μ„ ꡐ체
Object.setPrototypeOf(obj, parent); // obj.__proto__ = parent;

console.log(obj.x); // 1

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

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

// ν•¨μˆ˜ κ°μ²΄λŠ” prototype ν”„λ‘œνΌν‹°λ₯Ό μ†Œμœ ν•œλ‹€.
(function () {}).hasOwnProperty('prototype'); // true

// 일반 κ°μ²΄λŠ” prototype ν”„λ‘œνΌν‹°λ₯Ό μ†Œμœ ν•˜μ§€ μ•ŠλŠ”λ‹€.
({}).hasOwnProperty('prototype'); // false
Object.hasOwnProperty('prototype'); // true

prototype ν”„λ‘œνΌν‹°λŠ” μƒμ„±μž ν•¨μˆ˜κ°€ 생성할 객체(μΈμŠ€ν„΄μŠ€)의 ν”„λ‘œν† νƒ€μž…μ„ 가리킨닀. μƒμ„±μž ν•¨μˆ˜λ‘œμ„œ ν˜ΈμΆœν•  수 μ—†λŠ” ν•¨μˆ˜, 즉 non-constructor인 ν™”μ‚΄ν‘œ ν•¨μˆ˜μ™€ ES6 λ©”μ„œλ“œ μΆ•μ•½ ν‘œν˜„μœΌλ‘œ μ •μ˜ν•œ λ©”μ„œλ“œλŠ” prototype ν”„λ‘œνΌν‹°λ₯Ό μ†Œμœ ν•˜μ§€ μ•ŠμœΌλ©° ν”„λ‘œν† νƒ€μž…λ„ μƒμ„±ν•˜μ§€ μ•ŠλŠ”λ‹€.

// ν™”μ‚΄ν‘œ ν•¨μˆ˜λŠ” non-constructorλ‹€.
const Person = name => {
  this.name = name;
};

// non-constructorλŠ” prototype ν”„λ‘œνΌν‹°λ₯Ό μ†Œμœ ν•˜μ§€ μ•ŠλŠ”λ‹€.
console.log(Person.hasOwnProperty('prototype')); // false

// non-constructorλŠ” ν”„λ‘œν† νƒ€μž…μ„ μƒμ„±ν•˜μ§€ μ•ŠλŠ”λ‹€.
console.log(Person.prototype); // undefined

// ES6의 λ©”μ„œλ“œ μΆ•μ•½ ν‘œν˜„μœΌλ‘œ μ •μ˜ν•œ λ©”μ„œλ“œλŠ” non-constructorλ‹€.
const obj = {
  foo() {}
};

// non-constructorλŠ” prototype ν”„λ‘œν¬ν„°λ₯Ό μ†Œμœ ν•˜μ§€ μ•ŠλŠ”λ‹€.
console.log(obj.foo.hasOwnProperty('prototype')) // false

// non-constructorλŠ” ν”„λ‘œν† νƒ€μž…μ„ μƒμ„±ν•˜μ§€ μ•ŠλŠ”λ‹€.
console.log(obj.foo.prototype); // undefined

λͺ¨λ“  객체가 가지고 μžˆλŠ”(μ—„λ°€νžˆ λ§ν•˜λ©΄ Object.prototypeμœΌλ‘œλΆ€ν„° 상속받은) protto μ ‘κ·Όμž ν”„λ‘œν¬ν‹°μ™€ ν•¨μˆ˜ 객체만이 가지고 μžˆλŠ” prototype ν”„λ‘œνΌν‹°λŠ” κ²°κ΅­ λ™μΌν•œ ν”„λ‘œν† νƒ€μž…μ„ 가리킨닀.

κ΅¬λΆ„μ†Œμœ κ°’μ‚¬μš© μ£Όμ²΄μ‚¬μš© λͺ©μ 
__proto__
μ ‘κ·Όμž ν”„λ‘œνΌν‹°
λͺ¨λ“  κ°μ²΄ν”„λ‘œν† νƒ€μž…μ˜ μ°Έμ‘°λͺ¨λ“  객체객체가 μžμ‹ μ˜ ν”„λ‘œν† νƒ€μž…μ— μ ‘κ·Ό λ˜λŠ” κ΅μ²΄ν•˜κΈ° μœ„ν•΄ μ‚¬μš©
prototype
μ ‘κ·Όμž ν”„λ‘œνΌν‹°
constructorν”„λ‘œν† νƒ€μž…μ˜ μ°Έμ‘°μƒμ„±μž ν•¨μˆ˜μƒμ„±μž ν•¨μˆ˜κ°€ μžμ‹ μ΄ 생성할 객체(μΈμŠ€ν„΄μŠ€)의
ν”„λ‘œν† νƒ€μž…μ„ ν• λ‹Ήν•˜κΈ° μœ„ν•΄ μ‚¬μš©

❓ μƒμ„±μž ν•¨μˆ˜λ‘œ 객체λ₯Ό μƒμ„±ν•œ ν›„ _proto__ μ ‘κ·Όμž ν”„λ‘œνΌν‹°μ™€ prototype ν”„λ‘œνΌν‹°λ‘œ ν”„λ‘œν†  νƒ€μž… 객체에 μ ‘κ·Όν•΄ 보면

// μƒμ„±μž ν•¨μˆ˜
function Person(name) {
  this.name = name;
}ㅁ

const me = new Person('Lee');

// κ²°κ΅­ person.prototypeκ³Ό me.__proto__λŠ” κ²°κ΅­ λ™μΌν•œ ν”„λ‘œν† νƒ€μž…μ„ 가리킨닀.
console.log(Person.prototype === me.__proto__); // true

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

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

// μƒμ„±μž ν•¨μˆ˜
function Person(name) {
  this.name = name;
}

const me = new Person('Lee');

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

μœ„ μ˜ˆμ œμ—μ„œ Person μƒμ„±μž ν•¨μˆ˜λŠ” me 객체λ₯Ό μƒμ„±ν–ˆλ‹€ 이 λ•Œ me κ°μ²΄λŠ” ν”„λ‘œν† νƒ€μž…μ˜ constructor ν”„λ‘œνΌν‹°λ₯Ό 톡해 μƒμ„±μž ν•¨μˆ˜μ™€ μ—°κ²°λœλ‹€. me κ°μ²΄μ—λŠ” constructor ν”„λ‘œνΌν‹°κ°€ μ—†μ§€λ§Œ me 객체의 ν”„λ‘œν† νƒ€μž…μΈ Person.prototypeμ—λŠ” constructor ν”„λ‘œνΌν‹°κ°€ μžˆλ‹€. λ”°λΌμ„œ me κ°μ²΄λŠ” ν”„λ‘œν† νƒ€μž…μΈ Person.prototype의 constructor ν”„λ‘œνΌν‹°λ₯Ό 상속받아 μ‚¬μš©ν•  수 μžˆλ‹€.

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

λ¦¬ν„°λŸ΄ ν‘œκΈ°λ²•μ— μ˜ν•œ 객체 생성 방식

// 객체 λ¦¬ν„°λŸ΄
const obj = {};

// ν•¨μˆ˜ λ¦¬ν„°λŸ΄
const add = function (a, b) { return a + b;};

// λ°°μ—΄ λ¦¬ν„°λŸ΄
const arr = [1,2,3];

// μ •κ·œ ν‘œν˜„μ‹ λ¦¬ν„°λŸ΄
const regExp = /is/ig;

λ¦¬ν„°λŸ΄ ν‘œκΈ°λ²•μ— μ˜ν•΄ μƒμ„±λœ 객체도 λ¬Όλ‘  ν”„λ‘œν† νƒ€μž…μ€ μ‘΄μž¬ν•œλ‹€. ν•˜μ§€λ§Œ λ¦¬ν„°λŸ΄ ν‘œκΈ°λ²•μ— μ˜ν•΄ μƒμ„±λœ 객체의 경우 ν”„λ‘œν† νƒ€μž…μ˜ constructor ν”„λ‘œνΌν‹°κ°€ κ°€λ¦¬ν‚€λŠ” μƒμ„±μž ν•¨μˆ˜κ°€ λ°˜λ“œμ‹œ 객체λ₯Ό μƒμ„±ν•œ μƒμ„±μž ν•¨μˆ˜λΌκ³  단정할 수 μ—†λ‹€.

// obj κ°μ²΄λŠ” Object μƒμ„±μž ν•¨μˆ˜λ‘œ μƒμ„±ν•œ 객체가 μ•„λ‹ˆλΌ 객체 λ¦¬ν„°λŸ΄λ‘œ μƒμ„±ν–ˆλ‹€.
const obj = {};

// ν•˜μ§€λ§Œ obj 객체의 μƒμ„±μž ν•¨μˆ˜λŠ” Object μƒμ„±μž ν•¨μˆ˜λ‹€.
console.log(obj.constructor === Object); // true

μœ„ 예제의 obj κ°μ²΄λŠ” 객체 λ¦¬ν„°λŸ΄μ— μ˜ν•΄ μƒμ„±λœ 객체이닀. ν•˜μ§€λ§Œ obj의 κ°μ²΄λŠ” Object μƒμ„±μž ν•¨μˆ˜μ™€ constructor ν”„λ‘œνΌν‹°λ‘œ μ—°κ²°λ˜μ–΄ μžˆλ‹€. κ·Έλ ‡λ‹€λ©΄ 객체 λ¦¬ν„°λŸ΄μ— μ˜ν•΄ μƒμ„±λœ κ°μ²΄λŠ” 사싀 Object μƒμ„±μž ν•¨μˆ˜λ‘œ μƒμ„±λ˜λŠ” 것은 μ•„λ‹κΉŒ?

πŸ‘‰ Object μƒμ„±μž ν•¨μˆ˜ κ΅¬ν˜„ 방식

2μ—μ„œ Obejct μƒμ„±μž ν•¨μˆ˜μ— 인수λ₯Ό μ „λ‹¬ν•˜μ§€ μ•Šκ±°λ‚˜ undefined λ˜λŠ” null을 인수둜 μ „λ‹¬ν•˜λ©΄μ„œ ν˜ΈμΆœν•˜λ©΄ λ‚΄λΆ€μ μœΌλ‘œλŠ” 좔상 μ—°μ‚° OrdinaryObjectCreateλ₯Ό ν˜ΈμΆœν•˜μ—¬ Object.Prototype을 ν”„λ‘œν† νƒ€μž…μœΌλ‘œ κ°–λŠ” 빈 객체λ₯Ό μƒμ„±ν•œλ‹€.

πŸ’‘ 좔상 μ—°μ‚°

좔상 연산은 ECMAScript μ‚¬μ–‘μ—μ„œ λ‚΄λΆ€ λ™μž‘μ˜ κ΅¬ν˜„ μ•Œκ³ λ¦¬μ¦˜μ„ ν‘œν˜„ν•œ 것이닀. ECMAScipt μ‚¬μ–‘μ—μ„œ μ„€λͺ…을 μœ„ν•΄ μ‚¬μš©λ˜λŠ” ν•¨μˆ˜μ™€ μœ μ‚¬ν•œ μ˜μ‚¬λ„ μ½”λ“œλΌκ³  μ΄ν•΄ν•˜μž

// 1. new.target이 undefinedλ‚˜ Objectκ°€ μ•„λ‹Œ 경우
// new.target이 λͺ¨λ₯΄κ² μœΌλ©΄? μƒμ„±μž ν•¨μˆ˜
// μΈμŠ€ν„΄μŠ€ -> Foo.prototype -> Object.prototype 순으둜 ν”„λ‘œν† νƒ€μž… 체인이 μƒμ„±λœλ‹€.
class Foo extends Object {}
new Foo(); // Foo {}

// 2. Object μƒμ„±μž ν•¨μˆ˜μ— μ˜ν•œ 객체 생성
// μΈμˆ˜κ°€ μ „λ‹¬λ˜μ§€ μ•Šμ•˜μ„ λ•Œ 좔상 μ—°μ‚° OrdinaryObjectCreateλ₯Ό ν˜ΈμΆœν•˜μ—¬ 빈 객체λ₯Ό μƒμ„±ν•œλ‹€.
let obj = new Object();
console.log(obj); // {}

// 3. μΈμˆ˜κ°€ μ „λ‹¬λœ κ²½μš°μ—λŠ” 객체λ₯Ό λ³€ν™˜ν•œλ‹€.
// Number 객체 생성
obj = new Obeject(123);
console.log(obj); // Number {123}

// String 객체 생성
obj = new Object('123');
console.log(obj); // String {"123"}

πŸ‘‰ 객체 λ¦¬ν„°λŸ΄ 평가

객체 λ¦¬ν„°λŸ΄μ΄ 평가될 λ•ŒλŠ” 좔상 μ—°μ‚° OrdinaryObjectCreateλ₯Ό ν˜ΈμΆœν•˜μ—¬ 빈 객체λ₯Ό μƒμ„±ν•˜κ³  ν”„λ‘œνΌν‹°λ₯Ό μΆ”κ°€ν•˜λ„λ‘ μ •μ˜λ˜μ–΄ μžˆλ‹€.

이처럼 Obejct μƒμ„±μž ν•¨μˆ˜ 호좜과 객체 λ¦¬ν„°λŸ΄μ˜ ν‰κ°€λŠ” 좔상 μ—°μ‚° OrdinaryObjectCreateλ₯Ό ν˜ΈμΆœν•˜μ—¬ 빈 객체λ₯Ό μƒμ„±ν•˜λŠ” μ μ—μ„œ λ™μΌν•˜λ‚˜ new.target의 ν™•μΈμ΄λ‚˜ ν”„λ‘œνΌν‹°λ₯Ό μΆ”κ°€ν•˜λŠ” 처리 λ“± μ„ΈλΆ€λ‚΄μš©μ€ λ‹€λ₯΄λ‹€. λ”°λΌμ„œ 객체 λ¦¬ν„°λŸ΄μ— μ˜ν•΄ μƒμ„±λœ κ°μ²΄λŠ” Obejct μƒμ„±μž ν•¨μˆ˜κ°€ μƒμ„±ν•œ 객체가 μ•„λ‹ˆλ‹€

β€» μ΄λŸ¬ν•œ μ°¨μ΄λŠ” ν•¨μˆ˜ 객체의 κ²½μš°κ°€ 더 λͺ…ν™•ν•˜λ‹€.

12μž₯ 4.4절 Function μƒμ„±μž ν•¨μˆ˜μ—μ„œ μ‚΄νŽ΄λ³΄μ™”λ“―μ΄ Function μƒμ„±μž ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜μ—¬ μƒμ„±ν•œ ν•¨μˆ˜λŠ” λ ‰μ‹œμ»¬ μŠ€μ½”ν”„λ₯Ό λ§Œλ“€μ§€ μ•Šκ³  μ „μ—­ν•¨μˆ˜μΈ κ²ƒμ²˜λŸΌ μŠ€μ½”ν”„λ₯Ό μƒμ„±ν•˜λ©° ν΄λ‘œμ €λ„ λ§Œλ“€μ§€ μ•ŠλŠ”λ‹€. λ”°λΌμ„œ ν•¨μˆ˜ μ„ μ–Έλ¬Έ ν•¨μˆ˜ ν‘œν˜„μ‹μ„ ν‰κ°€ν•˜μ—¬ ν•¨μˆ˜ 객체λ₯Ό μƒμ„±ν•œ 것은 Function μƒμ„±μž ν•¨μˆ˜κ°€ μ•„λ‹ˆλ‹€. ν•˜μ§€λ§Œ constructor ν”„λ‘œνΌν‹°λ₯Ό 톡해 확인해 보면 fooν•¨μˆ˜μ˜ μƒμ„±μž ν•¨μˆ˜λŠ” Functionμƒμ„±μž ν•¨μˆ˜λ‹€.

// foo ν•¨μˆ˜λŠ” Function μƒμ„±μž ν•¨μˆ˜λ‘œ μƒμ„±ν•œ ν•¨μˆ˜ 객체가 μ•„λ‹ˆλΌ ν•¨μˆ˜ μ„ μ–Έλ¬ΈμœΌλ‘œ μƒμ„±ν–ˆλ‹€.
function foo() {}

// ν•˜μ§€λ§Œ constructor ν”„λ‘œνΌν‹°λ₯Ό 톡해 확인해보면 ν•¨μˆ˜ foo의 μƒμ„±μž ν•¨μˆ˜λŠ” Function μƒμ„±μž ν•¨μˆ˜λ‹€.
console.log(foo.constructor === Function); // true
객체 λ¦¬ν„°λŸ΄ ν‘œκΈ°λ²•μƒμ„±μž ν•¨μˆ˜ν”„λ‘œν† νƒ€μž…
객체 λ¦¬ν„°λŸ΄ObjectObject.prototype
ν•¨μˆ˜ λ¦¬ν„°λŸ΄FunctionFunction.prototype
λ°°μ—΄ λ¦¬ν„°λŸ΄ArrayArray.prototype
μ •κ·œ ν‘œν˜„μ‹ λ¦¬ν„°λŸ΄RegExpRexExp.prototype

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

κ°μ²΄λŠ” λ¦¬ν„°λŸ΄ ν‘œκΈ°λ²• λ˜λŠ” μƒμ„±μž ν•¨μˆ˜μ— μ˜ν•΄ 생성 κ²°κ΅­ λͺ¨λ“  객체 μƒμ„±μž ν•¨μˆ˜μ™€ μ—°κ²°λ˜μ–΄μžˆλ‹€.

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

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

μƒμ„±μž ν•¨μˆ˜λ‘œμ„œ ν˜ΈμΆœν•  수 μžˆλŠ” ν•¨μˆ˜, 즉 construcotrλŠ” ν•¨μˆ˜ μ •μ˜κ°€ ν‰κ°€λ˜μ–΄ ν•¨μˆ˜ 객체λ₯Ό μƒμ„±ν•˜λŠ” μ‹œμ μ— ν”„λ‘œν† νƒ€μž…λ„ λ”λΆˆμ–΄ μƒμ„±λœλ‹€.

// ν•¨μˆ˜ μ •μ˜(construcotr)κ°€ ν‰κ°€λ˜μ–΄ ν•¨μˆ˜ 객체λ₯Ό μƒμ„±ν•˜λŠ” μ‹œμ μ— ν”„λ‘œν† νƒ€μž…λ„ λ”λΆˆμ–΄ μƒμ„±λœλ‹€.
console.log(Person.prototyp); // {constructor: f}

// μƒμ„±μž ν•¨μˆ˜
function Person(name) {
	this.name = name;
}

ν•¨μˆ˜ ν˜Έμ΄μŠ€νŒ…μ— μ˜ν•΄ ν•¨μˆ˜ μ„ μ–Έλ¬ΈμœΌλ‘œ μ •μ˜ Person μƒμ„±μž ν•¨μˆ˜ λŸ°νƒ€μž„ 이전에 μžλ°”μŠ€ν¬λ¦½νŠΈ 엔진에 μ˜ν•΄ λ¨Όμ € μ‹€ν–‰λ˜μ–΄ ν•¨μˆ˜ 객체 생성 μ΄λ•Œ ν”„λ‘œν† νƒ€μž…λ„ λ”λΆˆμ–΄ 생성 μƒμ„±λœ ν”„λ‘œν† νƒ€μž…μ€ Person μƒμ„±μž ν•¨μˆ˜μ˜ prototype ν”„λ‘œνΌν‹°μ— 바인딩

//  ν•¨μˆ˜λ‘œμ„œ ν˜ΈμΆœν•  수 μ—†λŠ” ν•¨μˆ˜, 즉, non-constructorλŠ” ν”„λ‘œν† νƒ€μž…μ΄ μƒμ„±λ˜μ§€ μ•ŠλŠ”λ‹€.
// ν™”μ‚΄ν‘œ ν•¨μˆ˜λŠ” non-constructorλ‹€.
const Person = name => {
  this.name  = name;
};

// non-constructorλŠ” ν”„λ‘œν† νƒ€μž…μ΄ μƒμ„±λ˜μ§€ μ•ŠλŠ”λ‹€,
console.log(Person.prototype); // undefined

μƒμ„±λœ ν”„λ‘œν† νƒ€μž…μ€ 였직 constructor ν”„λ‘œνΌν‹°λ§Œμ„ κ°–λŠ” 객체 ν”„λ‘œν† νƒ€μž…λ„ 객체이고 λͺ¨λ“  κ°μ²΄λŠ” ν”„λ‘œν† νƒ€μž…μ„ κ°€μ§€λ―€λ‘œ ν”„λ‘œν† νƒ€μž…λ„ μžμ‹ μ˜ ν”„λ‘œν† νƒ€μž…μ„ κ°–λŠ”λ‹€. μƒμ„±λœ ν”„λ‘œν† νƒ€μž…μ˜ ν”„λ‘œν† νƒ€μž…μ€ Object.prototype이닀.

빌트인 μƒμ„±μž ν•¨μˆ˜κ°€ μ•„λ‹Œ μ‚¬μš©μž μ •μ˜ μƒμ„±μž ν•¨μˆ˜λŠ” μžμ‹ μ΄ ν‰κ°€λ˜μ–΄ ν•¨μˆ˜ 객체둜 μƒμ„±λ˜λŠ” μ‹œμ μ— ν”„λ‘œν† νƒ€μž…λ„ λ”λΆˆμ–΄ μƒμ„±λ˜λ©°, μƒμ„±λœ ν”„λ‘œν† νƒ€μž…μ˜ ν”„λ‘œν† νƒ€μž…μ€ μ–Έμ œλ‚˜ Object.prototype이닀.

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

Object String Number Function Array RegExp Date Promiseλ“±κ³Ό 같은 빌트인 μƒμ„±μž ν•¨μˆ˜λ„ 일반 ν•¨μˆ˜μ™€ λ§ˆμ°¬κ°€μ§€λ‘œ 빌트인 μƒμ„±μž ν•¨μˆ˜κ°€ μƒμ„±λ˜λŠ” μ‹œμ μ— ν”„λ‘œν† νƒ€μž…μ΄ 생성 μƒμ„±λœ ν”„λ‘œν† νƒ€μž…μ€ 빌트인 μƒμ„±μž ν•¨μˆ˜μ˜ prototype ν”„λ‘œνΌν‹°μ— λ°”μΈλ”©λœλ‹€.

λͺ¨λ“  빌트인 μƒμ„±μž ν•¨μˆ˜λŠ” μ „μ—­ 객체가 μƒμ„±λ˜λŠ” μ‹œμ μ— μƒμ„±λœλ‹€.

❓ μ „μ—­ κ°μ²΄λž€

μ „μ—­ κ°μ²΄λŠ” μ½”λ“œκ°€ μ‹€ν–‰λ˜κΈ° 이전 단계에 μžλ°”μŠ€ν¬λ¦½νŠΈ 엔진에 μ˜ν•΄ μƒμ„±λ˜λŠ” νŠΉμˆ˜ν•œ 객체닀.

μ „μ—­ κ°μ²΄λŠ” ν΄λΌμ΄μ–ΈνŠΈ μ‚¬μ΄λ“œ ν™˜κ²½(λΈŒλΌμš°μ €)μ—μ„œλŠ” window, μ„œλ²„ μ‚¬μ΄λ“œ(Node.js)μ—μ„œλŠ” global 객체λ₯Ό μ˜λ§ˆν•œλ‹€.
μ „μ—­κ°μ²΄λŠ” ν‘œμ€€ 빌트인 객체(Object, String, Number, Function, Array...)λ“€κ³Ό ν™˜κ²½μ— λ”°λ₯Έ 호슀트 객체(ν΄λΌμ΄λ„ˆνŠΈ Web API λ˜λŠ” Node.js의 호슀트 API), 그리고 var ν‚€μ›Œλ“œλ‘œ μ„ μ–Έν•œ μ „μ—­ λ³€μˆ˜μ™€ μ „μ—­ ν•¨μˆ˜λ₯Ό ν”„λ‘œνΌν‹°λ‘œ κ°–λŠ”λ‹€. Math Reflect JSON을 μ œμ™Έν•œ ν‘œμ€€ 빌트인 κ°μ²΄λŠ” μƒμ„±μž ν•¨μˆ˜λ‹€.

// μ „μ—­ 객체 windowλŠ” λΈŒλΌμš°μ €μ— μ’…μ†μ μ΄λ―€λ‘œ μ•„λž˜ μ½”λ“œλŠ” λΈŒλΌμš°μ € ν™˜κ²½μ—μ„œ μ‹€ν–‰ν•΄μ•Ό ν•œλ‹€.
// 빌트인 객체인 ObjectλŠ” μ „μ—­ 객체 window의 ν”„λ‘œνΌν‹°λ‹€.
window.Object === Object // true

객체가 μƒμ„±λ˜κΈ° 이전에 μƒμ„±μž ν•¨μˆ˜μ™€ ν”„λ‘œν† νƒ€μž…μ€ 이미 κ°μ²΄ν™”λ˜μ–΄ μ‘΄μž¬ν•œλ‹€. 이후 μƒμ„±μž ν•¨μˆ˜ λ˜λŠ” λ¦¬ν„°λŸ΄ ν‘œκΈ°λ²•μœΌλ‘œ 객체λ₯Ό μƒμ„±ν•˜λ©΄ ν”„λ‘œνƒ€μž…μ€ μƒμ„±λœ 객체의 [[Prototype]] λ‚΄λΆ€ μŠ¬λ‘―μ— ν• λ‹Ήλœλ‹€.

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

객체 생성 방식

  • 객체 λ¦¬ν„°λŸ΄
  • Object μƒμ„±μž ν•¨μˆ˜
  • μƒμ„±μž ν•¨μˆ˜
  • Object.create λ©”μ„œλ“œ
  • 클래슀(ES6)

이처럼 λ‹€μ–‘ν•œ λ°©μ‹μœΌλ‘œ μƒμ„±λœ λͺ¨λ“  κ°μ²΄λŠ” λ°©μ‹λ§ˆλ‹€ 세뢀적인 객체 생성 λ°©μ‹μ˜ μ°¨μ΄λŠ” μžˆμœΌλ‚˜ 좔상연산 OrdinaryObjectCreate에 μ˜ν•΄ μƒμ„±λœλ‹€λŠ” 곡톡점이 μžˆλ‹€.

좔상연산 OrdinaryObjectCreateλŠ” ν•„μˆ˜μ μœΌλ‘œ μžμ‹ μ΄ 생성할 객체의 ν”„λ‘œν† νƒ€μž…μ„ 인수둜 μ „λ‹¬λ°›λŠ”λ‹€. 그리고 μžμ‹ μ΄ 생성할 객체에 μΆ”κ°€ν•  ν”„λ‘œνΌν‹° λͺ©λ‘μ„ μ˜΅μ…˜μœΌλ‘œ 전달할 수 μžˆλ‹€.

좔상연산 OrdinaryObjectCreateλŠ” 빈 객체λ₯Ό μƒμ„±ν•œ ν›„, 객체에 μΆ”κ°€ν•  ν”„λ‘œνΌν‹° λͺ©λ‘μ΄ 인수둜 μ „λ‹¬λœ 경우 ν”„λ‘œνΌν‹°λ₯Ό 객체에 μΆ”κ°€ν•œλ‹€. 그리고 인수둜 전달받은 ν”„λ‘œν† νƒ€μž…μ„ μžμ‹ μ΄ μƒμ„±ν•œ 객체의 [[Prototype]] λ‚΄λΆ€ μŠ¬λ‘―μ— ν• λ‹Ήν•œ λ‹€μŒ, μƒμ„±ν•œ 객체λ₯Ό λ°˜ν™˜ν•œλ‹€.

즉, ν”„λ‘œν† νƒ€μž…μ€ 좔상 μ—°μ‚° OrdinaryObjectCreate에 μ „λ‹¬λ˜λŠ” μΈμˆ˜μ— μ˜ν•΄ κ²°μ • 이 μΈμˆ˜λŠ” 객체가 μƒμ„±λ˜λŠ” μ‹œμ μ— 객체 생성 방식에 μ˜ν•΄ κ²°μ •

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

μžλ°”μŠ€ν¬λ¦½νŠΈ 엔진은 객체 λ¦¬ν„°λŸ΄μ„ ν‰κ°€ν•˜μ—¬ 객체λ₯Ό 생성할 λ•Œ 좔상연산 OrdinaryObjectCreateλ₯Ό ν˜ΈμΆœν•œλ‹€.

μ΄λ•Œ 좔상 μ—°μ‚° OrdinaryObjectCreate에 μ „λ‹¬λ˜λŠ” ν”„λ‘œν† νƒ€μ••μ€ Object.prototype이닀. 즉, 객체 λ¦¬ν„°λŸ΄μ— μ˜ν•΄ μƒμ„±λ˜λŠ” 객체의 ν”„λ‘œν†  νƒ€μž…μ€ Object.prototype이닀.

const obj = { x : 1 };
  • 객체 λ¦¬ν„°λŸ΄ 평가
  • OrdinaryObjectCreateλ₯Ό 호좜
  • 객체 리터렐에 μ˜ν•΄ μƒμ„±λ˜λŠ” 객체의 ν”„λ‘œν†  νƒ€μž…μœΌλ‘œ Object.prototype 전달

μœ„μ˜ 예제 obj κ°μ²΄λŠ” Object.prototype을 ν”„λ‘œν† νƒ€μž…μœΌλ‘œ κ°–κ²Œ 되며 Object.prototype을 μƒμ†λ°›λŠ”λ‹€. obj κ°μ²΄λŠ” constructor ν”„λ‘œνΌν‹°μ™€ hasOwnProperty λ©”μ„œλ“œλ“±μ„ μ†Œμœ ν•˜μ§€λŠ” μ•Šμ•˜μ§€λ§Œ μžμ‹ μ˜ ν”„λ‘œν† νƒ€μž…μΈ Object.prototype의 constructor ν”„λ‘œνΌν‹°μ™€ hasOwnProperty λ©”μ„œλ“œλ₯Ό μžμ‹ μ˜ μžμ‚°μΈ κ²ƒμ²˜λŸΌ 자유둭게 μ‚¬μš© κ°€λŠ₯.

const obj = { x: 1 };

// 객체 λ¦¬ν„°λŸ΄μ— μ˜ν•΄ μƒμ„±λœ obj κ°μ²΄λŠ” Object.prototype을 μƒμ†λ°›λŠ”λ‹€.
console.log(obj.constructor === Object); // true
console.log(obj.hasOwnProperty('x')); // true

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

Object μƒμ„±μž ν•¨μˆ˜λ₯Ό 인수 없이 ν˜ΈμΆœν•˜λ©΄ 빈 객체 생성, Object μƒμ„±μž ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜λ©΄ 객체 λ¦¬ν„°λŸ΄κ³Ό λ§ˆμ°¬κ°€μ§€λ‘œ 좔상 μ—°μ‚° OrdinaryObjectCreateκ°€ ν˜ΈμΆœλœλ‹€. μ΄λ•Œ 좔상 μ—°μ‚° OrdinaryObjectCreate에 μ „λ‹¬λ˜λŠ” ν”„λ‘œν†  νƒ€μž…μ€ Object.prototype이닀.

const obj = new Object();
obj.x = 1; 
const obj = new Object();
obj.x = 1;

// Object μƒμ„±μž ν•¨μˆ˜μ— μ˜ν•΄ μƒμ„±λœ obj κ°μ²΄λŠ” Object.prototype을 μƒμ†λ°›λŠ”λ‹€.
console.log(obj.constructor === Object); // true
console.log(obj.hasOwnProperty('x'); // true

객체 λ¦¬ν„°λŸ΄κ³Ό Object μƒμ„±μž ν•¨μˆ˜μ— μ˜ν•œ 객체 생성 λ°©μ‹μ˜ μ°¨μ΄λŠ” ν”„λ‘œνΌν‹°λ₯Ό μΆ”κ°€ν•˜λŠ” 방식에 μžˆλ‹€. 객체 λ¦¬ν„°λŸ΄ 방식은 객체 λ¦¬ν„°λŸ΄ 내뢀에 ν”„λ‘œνΌν‹°λ₯Ό μΆ”κ°€ν•˜μ§€λ§Œ Object μƒμ„±μž ν•¨μˆ˜ 방식은 일단 빈 객체λ₯Ό μƒμ„±ν•œ 이후 ν”„λ‘œνΌν‹°λ₯Ό μΆ”κ°€ν•΄μ•Ό ν•œλ‹€.

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

new μ—°μ‚°μžμ™€ ν•¨κ»˜ μƒμ„±μž ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜μ—¬ μΈμŠ€ν„΄μŠ€λ₯Ό μƒμ„±ν•˜λ©΄ λ‹€λ₯Έ 객체 생성 방식과 λ§ˆμ°¬κ°€μ§€λ‘œ 좔상 μ—°μ‚° OrdinaryObjectCreateκ°€ ν˜ΈμΆœλœλ‹€. μ΄λ•Œ 좔상 μ—°μ‚° OrdinaryObjectCreate에 μ „λ‹€λΌλ˜λŠ” ν”„λ‘œν† νƒ€μž…μ€ μƒμ„±μž ν•¨μˆ˜μ˜ prototype ν”„λ‘œνΌν‹°μ— λ°”μΈλ”©λ˜μ–΄ μžˆλŠ” 객체닀. 즉, μƒμ„±μž ν•¨μˆ˜μ— μ˜ν•΄ μƒμ„±λ˜λŠ” 개게체의 ν”„λ‘œν† νƒ€μž…μ€ μƒμ„±μž ν•¨μˆ˜μ˜ prototype ν”„λ‘œνΌν‹°μ— λ°”μΈλ”©λ˜μ–΄ μžˆλŠ” 객체닀.

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

const me = new Person('Lee');

ν‘œμ€€ 빌트인 객체인 Object μƒμ„±μž ν•¨μˆ˜μ™€ λ”λΆˆμ–΄ μƒμ„±λœ Object.prototype은 λ‹€μ–‘ν•œ 빌트인 λ©”μ„œλ“œλ₯Ό κ°–κ³ μžˆμ§€λ§Œ μ‚¬μš©μž μ •μ˜ μƒμ„±μž ν•¨μˆ˜ Personκ³Ό λ”λΆˆμ–΄ μƒμ„±λœ ν”„λ‘œν† νƒ€μž… Person.prototype의 ν”„λ‘œνΌν‹°λŠ” constructor뿐이닀.

post-custom-banner

0개의 λŒ“κΈ€