🌸17μž₯. μƒμ„±μž ν•¨μˆ˜μ— μ˜ν•œ 객체 생성

10μž₯ β€œκ°μ²΄ λ¦¬ν„°λŸ΄β€μ—μ„œ μ‚΄νŽ΄λ³Έ 객체 λ¦¬ν„°λŸ΄μ— μ˜ν•œ 객체 생성 방식 외에, 객체λ₯Ό μƒμ„±ν•˜λŠ” λ‹€μ–‘ν•œ 방법에 λŒ€ν•œ λ‚΄μš©μ„ μ‚΄νŽ΄λ³Ό μ˜ˆμ •μ΄λ‹€.

βœ…17.1 Object μƒμ„±μž ν•¨μˆ˜

μƒμ„±μž ν•¨μˆ˜(constructor)λž€, new μ—°μ‚°μžμ™€ ν•¨κ»˜ ν˜ΈμΆœν•˜μ—¬ 객체(μΈμŠ€ν„΄μŠ€)λ₯Ό μƒμ„±ν•˜λŠ” ν•¨μˆ˜
  • μΈμŠ€ν„΄μŠ€(instance) : μƒμ„±μž ν•¨μˆ˜μ— μ˜ν•΄ μƒμ„±λœ 객체

  • μžλ°”μŠ€ν¬λ¦½νŠΈμ—μ„œλŠ” Object μƒμ„±μž ν•¨μˆ˜ 이외에도 String, Number, Boolean, Function, Array, Date, RegExp, Promise λ“±μ˜ λΉŒλ“œμΈ(built-in) μƒμ„±μž ν•¨μˆ˜λ₯Ό 제곡

βœ…17.2 μƒμ„±μž ν•¨μˆ˜

객체 λ¦¬ν„°λŸ΄({})에 μ˜ν•œ 객체 생성 λ°©μ‹μ˜ 문제점

객체 λ¦¬ν„°λŸ΄μ— μ˜ν•œ 객체 생성 방식은 직관적이고 κ°„νŽΈν•˜μ§€λ§Œ, 단 ν•˜λ‚˜μ˜ 객체만 μƒμ„±ν•œλ‹€λŠ” λ¬Έμ œκ°€ μžˆλ‹€.

const circle1 = {
    radius: 5,
    getDiameter() {
        return 2 * this.radius;
    },
};

const circle2 = {
    radius: 10,
    getDiameter() {
        return 2 * this.radius;
    },
};

console.log(circle1.getDiameter()); //10
console.log(circle2.getDiameter()); //20

κ°μ²΄λŠ” λ‹€μŒ 2κ°€μ§€λ₯Ό ν‘œν˜„ν•  수 μžˆλ‹€.

  1. ν”„λ‘œνΌν‹°λ₯Ό 톡해 객체 고유의 **μƒνƒœ(state)**λ₯Ό ν‘œν˜„

  2. λ©”μ„œλ“œλ₯Ό 톡해 μƒνƒœ 데이터인 ν”„λ‘œνΌν‹°λ₯Ό μ°Έμ‘°ν•˜κ³  μ‘°μž‘ν•˜λŠ” **λ™μž‘(behavior)**을 ν‘œν˜„

μƒνƒœ(state)의 κ²½μš°λŠ” κ°μ²΄λ§ˆλ‹€ λ‹€λ₯Έ 값을 κ°€μ§ˆ 수 μžˆμ§€λ§Œ, λ©”μ„œλ“œ(behavior)의 κ²½μš°λŠ” λ‚΄μš©μ΄ λ™μΌν•œ κ²½μš°κ°€ μΌλ°˜μ μ΄λ‹€.

ν•˜μ§€λ§Œ, 객체 λ¦¬ν„°λŸ΄λ‘œ 객체λ₯Ό ν‘œν˜„ν•˜λŠ” 경우, ν”„λ‘œνΌν‹°μ˜ ꡬ쑰가 동일함에도 λΆˆκ΅¬ν•˜κ³ , 맀번 같은 ν”„λ‘œνΌν‹°μ™€ λ©”μ„œλ“œλ₯Ό κΈ°μˆ ν•΄μ•Όν•œλ‹€.

μƒμ„±μž ν•¨μˆ˜μ— μ˜ν•œ 객체 생성 λ°©μ‹μ˜ μž₯점

객체λ₯Ό μƒμ„±ν•˜κΈ° μœ„ν•œ ν…œν”Œλ¦Ώ(클래슀)처럼 μƒμ„±μž ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•˜μ—¬ ν”„λ‘œνΌν‹° ꡬ쑰가 λ™μΌν•œ 객체 μ—¬λŸ¬κ°œλ₯Ό κ°„νŽΈν•˜κ²Œ 생성할 수 μžˆλ‹€.

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

// μΈμŠ€ν„΄μŠ€ 생성
const circle1 = new Circle(5);
const circle2 = new Circle(10);
console.log(circle1.getDiameter()); //10
console.log(circle2.getDiameter()); //20

// new μ—°μ‚°μžμ™€ ν•¨κ»˜ ν˜ΈμΆœν•˜μ§€ μ•Šμ€ 경우, 일반 ν•¨μˆ˜λ‘œ λ™μž‘
const circle3 = Circle(15);
console.log(circle3); // undefined
console.log(radius); // 15
  • 참고둜, thisλŠ” 객체 μžμ‹ μ˜ ν”„λ‘œνΌν‹°λ‚˜ λ©”μ„œλ“œλ₯Ό μ°Έμ‘°ν•˜κΈ° μœ„ν•œ 자기 μ°Έμ‘° λ³€μˆ˜(self-referencing varaible)둜, thisκ°€ κ°€λ¦¬ν‚€λŠ” κ°’(this 바인딩)은 ν•¨μˆ˜ 호좜 방식에 따라 λ™μ μœΌλ‘œ κ²°μ •λœλ‹€.

  • μƒμ„±μž ν•¨μˆ˜ λ‚΄λΆ€μ˜ thisλŠ” μƒμ„±μž ν•¨μˆ˜κ°€ 생성할 μΈμŠ€ν„΄μŠ€λ₯Ό 가리킨닀.

μžλ°”μŠ€ν¬λ¦½νŠΈμ—μ„œμ˜ μƒμ„±μž ν•¨μˆ˜

μžλ°”μ™€ 같은 클래슀 기반 객체지ν–₯μ–Έμ–΄μ˜ μƒμ„±μžμ™€λŠ” λ‹€λ₯΄κ²Œ, μžλ°”μŠ€ν¬λ¦½νŠΈμ˜ μƒμ„±μžλŠ” ν˜•μ‹μ΄ μ •ν•΄μ Έμžˆμ§€ μ•Šλ‹€.

  • 일반 ν•¨μˆ˜μ™€ λ™μΌν•œ λ°©λ²•μœΌλ‘œ μƒμ„±μž ν•¨μˆ˜λ₯Ό μ •μ˜ν•˜κ³ 

  • new μ—°μ‚°μžμ™€ ν•¨κ»˜ ν˜ΈμΆœν•˜λ©΄ ν•΄λ‹Ή ν•¨μˆ˜λŠ” μƒμ„±μž ν•¨μˆ˜λ‘œ λ™μž‘ν•œλ‹€.

λ”°λΌμ„œ, λ§Œμ•½ new μ—°μ‚°μžμ™€ ν•¨κ»˜ μƒμ„±μž ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜μ§€ μ•ŠμœΌλ©΄, 일반 ν•¨μˆ˜λ‘œ λ™μž‘ν•œλ‹€.

new.target

일반 ν•¨μˆ˜μ™€ μƒμ„±μž ν•¨μˆ˜μ— ν˜•μ‹ μ°¨μ΄λŠ” μ—†μ§€λ§Œ, new μ—°μ‚°μžμ™€ ν•¨κ»˜ ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜λ©΄, ν•΄λ‹Ή ν•¨μˆ˜λŠ” μƒμ„±μž ν•¨μˆ˜λ‘œ λ™μž‘ν•œλ‹€.

**new.target**μ΄λž€, ES6에 λ„μž…λ˜μ–΄ new μ—°μ‚°μžμ™€ ν•¨κ»˜ μƒμ„±μž ν•¨μˆ˜λ‘œμ„œ ν˜ΈμΆœλ˜μ—ˆλŠ”μ§€ 확인할 수 μžˆλŠ” 문법이닀.

  • new μ—°μ‚°μžμ™€ ν•¨κ»˜ μƒμ„±μž ν•¨μˆ˜λ‘œμ„œ 호좜되면 : ν•¨μˆ˜ λ‚΄λΆ€μ˜ new.target은 ν•¨μˆ˜ μžμ‹ μ„ 가리킨닀.

  • new μ—°μ‚°μžμ™€ 없이 일반 ν•¨μˆ˜λ‘œμ„œ 호좜되면 : ν•¨μˆ˜ λ‚΄λΆ€μ˜ new.target은 undefinedλ₯Ό 가리킨닀.

// μƒμ„±μž ν•¨μˆ˜
function Circle(radius) {
    // 이 ν•¨μˆ˜κ°€ new μ—°μ‚°μžμ™€ ν•¨κ»˜ ν˜ΈμΆœλ˜μ§€ μ•Šμ•˜λ‹€λ©΄, new.target은 undefined
    if (!new.target) {
        return new Circle(radius);
    }
    this.radius = radius;
    this.getDiameter = function () {
        return 2 * this.radius;
    };
}

// new μ—°μ‚°μž 없이 μƒμ„±μž ν˜ΈμΆœν•˜μ—¬λ„ new.target을 톡해 μƒμ„±μž ν•¨μˆ˜λ‘œμ„œ ν˜ΈμΆœλœλ‹€.
const circle = Circle(10);
console.log(circle); // Circle { radius: 10, getDiameter: [Function (anonymous)]

μŠ€μ½”ν”„ 세이프 μƒμ„±μž νŒ¨ν„΄

IE 와 같이 new.target을 μ§€μ›ν•˜μ§€ μ•ŠλŠ” λΈŒλΌμš°μ € ν™˜κ²½μ—μ„œ, μƒμ„±μž ν•¨μˆ˜λ₯Ό 보μž₯ν•˜λŠ” 방법이닀.

// μƒμ„±μž ν•¨μˆ˜
function Circle(radius) {
    // 이 ν•¨μˆ˜κ°€ new μ—°μ‚°μžμ™€ ν•¨κ»˜ ν˜ΈμΆœλ˜μ§€ μ•Šμ•˜λ‹€λ©΄, 이 μ‹œμ μ˜ thisλŠ” μ „μ—­ 객체 windowλ₯Ό 가리킴
    // 즉, this λŠ” Circleκ³Ό ν”„λ‘œν† νƒ€μž…μ— μ˜ν•΄ μ—°κ²°λ˜μ§€ μ•ŠλŠ”λ‹€.
    if (!(this instanceof Circle)) {
        return new Circle(radius);
    }
    this.radius = radius;
    this.getDiameter = function () {
        return 2 * this.radius;
    };
}

// new μ—°μ‚°μž 없이 μƒμ„±μž ν˜ΈμΆœν•˜μ—¬λ„ μƒμ„±μž ν•¨μˆ˜λ‘œμ„œ ν˜ΈμΆœλœλ‹€.
const circle = Circle(10);
console.log(circle); // Circle { radius: 10, getDiameter: [Function (anonymous)]

μŠ€μ½”ν”„ 세이프 μƒμ„±μž νŒ¨ν„΄μ€ λŒ€λΆ€λΆ„μ˜ 빌트인 μƒμ„±μž ν•¨μˆ˜μ— λŒ€ν•΄μ„œλ„ μ μš©λ˜μ–΄, new μ—°μ‚°μžμ™€ ν•¨κ»˜ ν˜ΈμΆœλ˜μ—ˆλŠ”μ§€λ₯Ό 확인 ν›„ μ μ ˆν•œ 값을 λ°˜ν™˜μ‹œν‚¨λ‹€.

  • 단, μ›μ‹œνƒ€μž…μ˜ 빌트인 μƒμ„±μž ν•¨μˆ˜( Number, String, Boolean ) 에 λŒ€ν•΄μ„œλŠ” 이λ₯Ό 보μž₯ν•˜μ§€ μ•Šκ³ , μ›μ‹œ 값을 λ°˜ν™˜ν•˜κΈ°λ„ ν•œλ‹€.

// **Object, Function** : new μƒμ„±μž 없이 ν˜ΈμΆœν•΄λ„ new μ—°μ‚°μžμ™€ ν•¨κ»˜ ν˜ΈμΆœν–ˆμ„ λ•Œμ™€ λ™μΌν•˜κ²Œ λ™μž‘
const obj = Object();
console.log(obj); //{}

// **Number, String, Boolean** : new μ—°μ‚°μž 없이 ν˜ΈμΆœν•˜λ©΄ μ›μ‹œ κ°’ λ°˜ν™˜
const num = Number("123");
console.log(num, typeof num); // 123 number

βœ…17.3 μƒμ„±μž ν•¨μˆ˜μ˜ μΈμŠ€ν„΄μŠ€ 생성 κ³Όμ •

λ¨Όμ € μƒμ„±μž ν•¨μˆ˜μ˜ 역할은 λ‹€μŒκ³Ό κ°™λ‹€.

  1. [ν•„μˆ˜] ν”„λ‘œνΌν‹° ꡬ쑰가 λ™μΌν•œ μΈμŠ€ν„΄μŠ€λ₯Ό μƒμ„±ν•˜κΈ° μœ„ν•œ ν…œν”Œλ¦Ώ(클래슀)λ‘œμ„œ λ™μž‘ν•˜μ—¬ μΈμŠ€ν„΄μŠ€λ₯Ό 생성

  2. [μ˜΅μ…˜] μƒμ„±λœ μΈμŠ€ν„΄μŠ€λ₯Ό μ΄ˆκΈ°ν™”(μΈμŠ€ν„΄μŠ€ ν”„λ‘œνΌν‹° μΆ”κ°€ 및 μ΄ˆκΈ°κ°’ ν• λ‹Ή)

new μ—°μ‚°μžμ™€ ν•¨κ»˜ μƒμ„±μž ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜λ©΄, μžλ°”μŠ€ν¬λ¦½νŠΈ 엔진은 λ‹€μŒκ³Ό 같은 과정을 거쳐 μ•”λ¬΅μ μœΌλ‘œ μΈμŠ€ν„΄μŠ€λ₯Ό μƒμ„±ν•˜κ³  μΈμŠ€ν„΄μŠ€λ₯Ό μ΄ˆκΈ°ν™”ν•œ ν›„ μ•”λ¬΅μ μœΌλ‘œ μΈμŠ€ν„΄μŠ€λ₯Ό λ°˜ν™˜ν•œλ‹€.

1️⃣ μΈμŠ€ν„΄μŠ€ 생성과 this 바인딩

λŸ°νƒ€μž„ 이전에 μ•”λ¬΅μ μœΌλ‘œ 빈 객체가 μƒμ„±λœλ‹€.

  • 빈 객체 : 아직은 λ―Έμ™„μ„±λœ μƒμ„±μž ν•¨μˆ˜κ°€ μƒμ„±ν•œ μΈμŠ€ν„΄μŠ€

  • 이 빈 객체(μΈμŠ€ν„΄μŠ€)λŠ” this에 λ°”μΈλ”©λœλ‹€.

    • λ”°λΌμ„œ, μƒμ„±μž ν•¨μˆ˜ λ‚΄λΆ€μ˜ thisκ°€ μƒμ„±μž ν•¨μˆ˜κ°€ 생성할 μΈμŠ€ν„΄μŠ€λ₯Ό 가리킴

// μƒμ„±μž ν•¨μˆ˜
function Circle(radius) {
    // 1️⃣ μ•”λ¬΅μ μœΌλ‘œ μΈμŠ€ν„΄μŠ€κ°€ μƒμ„±λ˜κ³  this에 λ°”μΈλ”©λœλ‹€.
    console.log(this); // Circle {}
    this.radius = radius;
    this.getDiameter = function () {
        return 2 * this.radius;
    };
}

🧐 λ°”μΈλ”©μ΄λž€?

  • μ‹λ³„μžμ™€ 값을 μ—°κ²°ν•˜λŠ” κ³Όμ •

  • λ³€μˆ˜ μ„ μ–Έ : λ³€μˆ˜ 이름(μ‹λ³„μž)와 ν™•λ³΄λœ λ©”λͺ¨λ¦¬ κ³΅κ°„μ˜ μ£Όμ†Œλ₯Ό λ°”μΈλ”©ν•˜λŠ” 것

  • this 바인딩 : this와 thisκ°€ 가리킬 객체λ₯Ό 바인딩

2️⃣ μΈμŠ€ν„΄μŠ€ μ΄ˆκΈ°ν™”

μƒμ„±μž λͺΈμ²΄μ— κΈ°μˆ λ˜μ–΄ μžˆλŠ” μ½”λ“œκ°€ ν•œ 쀄씩 μ‹€ν–‰λ˜λ©°, this에 λ°”μΈλ”©λ˜μ–΄ μžˆλŠ” μΈμŠ€ν„΄μŠ€λ₯Ό μ΄ˆκΈ°ν™”ν•œλ‹€.

  • this에 λ°”μΈλ”©λ˜μ–΄ μžˆλŠ” μΈμŠ€ν„΄μŠ€μ— ν”„λ‘œνΌν‹°λ‚˜ λ©”μ„œλ“œλ₯Ό μΆ”κ°€ν•˜κ³ 

  • μƒμ„±μž ν•¨μˆ˜κ°€ 인수둜 전달받은 μ΄ˆκΈ°κ°’μ„ μΈμŠ€ν„΄μŠ€ ν”„λ‘œνΌν‹°μ— ν• λ‹Ήν•˜μ—¬ μ΄ˆκΈ°ν™”ν•˜κ±°λ‚˜ κ³ μ •κ°’ ν• λ‹Ή

// μƒμ„±μž ν•¨μˆ˜
function Circle(radius) {
    // 1️⃣ μ•”λ¬΅μ μœΌλ‘œ μΈμŠ€ν„΄μŠ€κ°€ μƒμ„±λ˜κ³  this에 λ°”μΈλ”©λœλ‹€.
    // 2️⃣ this에 바인딩 λ˜μ–΄ μžˆλŠ” μΈμŠ€ν„΄μŠ€λ₯Ό μ΄ˆκΈ°ν™”ν•œλ‹€.
    this.radius = radius;
    this.getDiameter = function () {
        return 2 * this.radius;
    };
}

3️⃣ μΈμŠ€ν„΄μŠ€ λ°˜ν™˜

μƒμ„±μž ν•¨μˆ˜ λ‚΄λΆ€μ—μ„œ λͺ¨λ“  μ²˜λ¦¬κ°€ λλ‚˜λ©΄, μ™„μ„±λœ μΈμŠ€ν„΄μŠ€κ°€ λ°”μΈλ”©λœ thisλ₯Ό μ•”λ¬΅μ μœΌλ‘œ λ°˜ν™˜ν•œλ‹€.

// μƒμ„±μž ν•¨μˆ˜
function Circle(radius) {
    // 1️⃣ μ•”λ¬΅μ μœΌλ‘œ μΈμŠ€ν„΄μŠ€κ°€ μƒμ„±λ˜κ³  this에 λ°”μΈλ”©λœλ‹€.
    // 2️⃣ this에 바인딩 λ˜μ–΄ μžˆλŠ” μΈμŠ€ν„΄μŠ€λ₯Ό μ΄ˆκΈ°ν™”ν•œλ‹€.
    this.radius = radius;
    this.getDiameter = function () {
        return 2 * this.radius;
    };

    // 3️⃣ μ™„μ„±λœ μΈμŠ€ν„΄μŠ€κ°€ λ°”μΈλ”©λœ this(= μΈμŠ€ν„΄μŠ€)κ°€ μ•”λ¬΅μ μœΌλ‘œ λ°˜ν™˜λœλ‹€.
}

// μΈμŠ€ν„΄μŠ€λ₯Ό 생성, Circle μƒμ„±μž ν•¨μˆ˜λŠ” μ•”λ¬΅μ μœΌλ‘œ this(Circle μΈμŠ€ν„΄μŠ€)λ₯Ό λ°˜ν™˜ν•œλ‹€.
const circle = new Circle(10);
console.log(circle); // Circle { radius: 10, getDiameter: [Function (anonymous)]

λ§Œμ•½ μ•”λ¬΅μ μœΌλ‘œ thisλ₯Ό λ°˜ν™˜ν•˜λŠ” λŒ€μ‹ ,

λ‹€λ₯Έ 객체λ₯Ό λͺ…μ‹œμ μœΌλ‘œ λ°˜ν™˜ν•  경우, return문에 λͺ…μ‹œν•œ 객체가 λ°˜ν™˜λœλ‹€.

λ˜ν•œ λͺ…μ‹œμ μœΌλ‘œ μ›μ‹œ 값을 λ°˜ν™˜ν•˜λ©΄, μ›μ‹œ κ°’ λ°˜ν™˜μ€ λ¬΄μ‹œλ˜κ³  μ•”λ¬΅μ μœΌλ‘œ thisκ°€ λ°˜ν™˜λœλ‹€.

// μƒμ„±μž ν•¨μˆ˜
function Circle(radius) {
    this.radius = radius;
    this.getDiameter = function () {
        return 2 * this.radius;
    };
    return 100; // ❗λͺ…μ‹œμ μœΌλ‘œ μ›μ‹œ 값을 λ°˜ν™˜ν•˜λ©΄, μ›μ‹œ κ°’ λ°˜ν™˜μ€ λ¬΄μ‹œλ˜κ³  μ•”λ¬΅μ μœΌλ‘œ this λ°˜ν™˜
}

// μΈμŠ€ν„΄μŠ€λ₯Ό 생성
const circle = new Circle(10);
console.log(circle); // Circle { radius: 10, getDiameter: [Function (anonymous)

Last updated