λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°
🌌 | WEB DEV/Vanilla JS

JS_κΈ°λ³Έ 문법 (24)_ μƒμ„±μž ν•¨μˆ˜

by KASSID 2023. 3. 31.

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

ν•¨μˆ˜λŠ” μž¬μ‚¬μš©κ°€λŠ₯ν•œ μ½”λ“œλ₯Ό λ¬ΆλŠ” 것 외에도 객체λ₯Ό μƒμ„±ν•˜λŠ” 역할을 μˆ˜ν–‰ν•  수 μžˆλ‹€.

β€» function으둜 μ„ μ–Έλœ ν•¨μˆ˜λŠ” 기본적으둜 μƒμ„±μž ν•¨μˆ˜μ˜ κΈ°λŠ₯을 κ°–λŠ”λ‹€.

 

 

μ˜ˆμ‹œ) 객체 생성

const student1 = {
  name : 'Sam',
  idNum : 20,
  say () {
    return `μ•ˆλ…•ν•˜μ„Έμš”. ${idNum}번 ${name}μž…λ‹ˆλ‹€.`;
  }
};

const student2 = {
  name : 'Tom',
  idNum : 25,
  say () {
    return `μ•ˆλ…•ν•˜μ„Έμš”. ${idNum}번 ${name}μž…λ‹ˆλ‹€.`;
  }
};

μœ„μ™€ 같이 λΉ„μŠ·ν•œ ν˜•νƒœμ˜ 객체λ₯Ό μ—¬λŸ¬κ°œ λ§Œλ“€μ–΄μ•Όν•˜λŠ” 경우 같은 μ½”λ“œλ₯Ό λ°˜λ³΅ν•˜λŠ” 것이기 λ•Œλ¬Έμ—

ν•¨μˆ˜λ₯Ό ν™œμš©ν•˜λ©΄ λ”μš± νŽΈλ¦¬ν•˜κ²Œ κ΅¬ν˜„ν•  수 μžˆλ‹€.

 

 

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

  - ν•¨μˆ˜λͺ…을 λŒ€λ¬Έμžλ‘œ μ •μ˜ν•œλ‹€.
  - return 문이 μ‘΄μž¬ν•˜μ§€ μ•ŠλŠ”λ‹€. (객체λ₯Ό λ°˜ν™˜ν•˜λŠ” ν•¨μˆ˜λž‘ 닀름)
  - μƒμ„±μž ν•¨μˆ˜λ₯Ό new μ—°μ‚°μžμ™€ ν•¨κ»˜ μ‚¬μš©ν•œλ‹€. (newλ₯Ό μ‚¬μš©ν•΄μ•Ό μƒμ„±μž ν•¨μˆ˜μ˜ κΈ°λŠ₯을 μˆ˜ν–‰ν•¨, μ•ˆ 뢙이면 μΌλ°˜ν•¨μˆ˜)
  - ' this.~ ' λ‘œ 객체의 ν”„λ‘œνΌν‹°λ“€μ„ μ •μ˜ν•œλ‹€.
  - μƒμ„±μž ν•¨μˆ˜μ—μ„œλŠ” λ©”μ„œλ“œ μ •μ˜κ°€ λΆˆκ°€ν•˜λ‹€.

 

μ˜ˆμ‹œ)

function Student(name, idNum) {
  this.name = name;
  this.idNum = idNum;
  this.say = function() {
    return `μ•ˆλ…•ν•˜μ„Έμš”. ${idNum}번 ${name}μž…λ‹ˆλ‹€.`;
  }
}

 

 

const student1 = new Student('Sam', 20);
const student2 = new Student('Tom', 25);

 

이처럼 new μ—°μ‚°μžλ₯Ό λΆ™μ—¬μ„œ μ‚¬μš©ν•΄μ•Όλ§Œ μ˜λ„ν•œλŒ€λ‘œ 객체λ₯Ό 생성할 수 μžˆλ‹€.

 

λ§Œμ•½ 이λ₯Ό μ‚¬μš©ν•˜μ§€ μ•ŠλŠ”λ‹€λ©΄ undefinedλ₯Ό λ°˜ν™˜ν•œλ‹€.

// new μ—°μ‚°μžλ₯Ό μ‚¬μš©ν•˜μ§€ μ•Šμ€ 경우
const student3 = Student('David', 15);

console.log(student3);

>>> undefined

 


2. μƒμ„±μž ν•¨μˆ˜λ‘œ λ§Œλ“€μ–΄μ§„ 객체

μƒμ„±μž ν•¨μˆ˜λ‘œ λ§Œλ“€μ–΄μ§„ κ°μ²΄λŠ” λ‹€λ₯Έ λ°©μ‹μ˜ 객체와 λ‹€λ₯΄λ‹€.

 

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

ν”„λ‘œν† νƒ€μž…μ€ JSμ—μ„œ 객체지ν–₯을 κ΅¬ν˜„ν•  수 μžˆλ„λ‘ λ•λŠ” 역할을 ν•œλ‹€.

μ΄ˆκΈ°μ—λŠ” ν΄λž˜μŠ€κ°€ μ‘΄μž¬ν•˜μ§€ μ•Šμ•˜κΈ° λ•Œλ¬Έμ— ν”„λ‘œν† νƒ€μž…μœΌλ‘œ κ΅¬ν˜„μ„ ν•˜μ˜€λ‹€.

 

ν΄λž˜μŠ€μ— λΉ„ν•΄ λ’€λ–¨μ–΄μ§€λŠ” 것이 μ•„λ‹Œ μ‚¬μš©μ— 따라 더 κ°•λ ₯ν•˜κ²Œ μ‚¬μš©μ΄ κ°€λŠ₯ν•˜λ‹€.

λ˜ν•œ 클래슀 μžμ²΄κ°€ ν”„λ‘œν† νƒ€μž…μ„ 기반으둜 λ§Œλ“€μ–΄μ‘Œλ‹€!

 

이에 λŒ€ν•œ μžμ„Έν•œ μ΄μ•ΌκΈ°λŠ” 좔후에 λ”°λ‘œ λ‹€λ£¨κΈ°λ‘œ ν•˜κ³  κ°„λ‹¨νžˆλ§Œ μ•Œμ•„λ³΄μž!

 

 

μ˜ˆμ‹œ) μƒμ„±μž ν•¨μˆ˜μ™€ 객체 생성

function Player(name, job){
  this.name = name;
  this.job = job;
  this.info = function () {
    return `μ†Œν™˜μ‚¬λͺ… : ${this.name} | 직업ꡰ : ${this.job}`;
  }
}

const player1 = new Player('Kassid', '전사');

console.log(player1);

>>> Player {name: 'Kassid', job: '전사', info: Ζ’}

 

μœ„μ˜ 객체에 ν”„λ‘œν† νƒ€μž…μ„ μ΄μš©ν•˜μ—¬ μƒˆλ‘œμš΄ ν”„λ‘œνΌν‹°λ₯Ό μΆ”κ°€ν•΄λ³΄μž!

//.prototype을 μ΄μš©ν•˜μ—¬ μƒˆ ν”„λ‘œνΌν‹° μΆ”κ°€
Player.prototype.attack = function() {
  return '곡격!';
}

기쑴에 미리 μƒμ„±ν•œ 객체에도 μƒˆλ‘œμš΄ ν”„λ‘œνΌν‹°κ°€ 생긴 것을 μ•Œμˆ˜ μžˆλ‹€.

console.log(player1.attack());

>>> 곡격!

 

ν”„λ‘œν† νƒ€μž…μ„ μˆ˜μ •ν•˜λ©΄ μƒˆλ‘œ λ§Œλ“€μ–΄μ§ˆ μ˜ˆμ •μΈ 객체와 이미 μ‘΄μž¬ν•˜λŠ” 객체 λͺ¨λ‘ ν•΄λ‹Ή λ‚΄μš©μ΄ μ μš©λœλ‹€.

 

λΉ„μœ ν•˜μžλ©΄ λ³Έμ‚¬μ—μ„œ λ°°ν¬ν•˜λŠ” 메뉴얼과 같은 κΈ°λŠ₯을 ν•œλ‹€.

 

ν•˜μ§€λ§Œ μ—¬κΈ°μ„œ μ£Όμ˜ν•  점은 ν”„λ‘œν† νƒ€μž…μ„ μ΄μš©ν•΄ μΆ”κ°€ν•œ 것은

일반 ν”„λ‘œνΌν‹°μ™€ λ‹€λ₯΄λ‹€λŠ” 것이닀. (μΈμŠ€ν„΄μŠ€ vs ν”„λ‘œν† νƒ€μž…)

console.log(player1);

>>> 
Player {name: 'Kassid', job: '전사', info: Ζ’}
    info: Ζ’ ()
    job: "전사"
    name: "Kassid"
    [[Prototype]]: Object
        attack: Ζ’ ()
        constructor: Ζ’ Player(name, job)
        [[Prototype]]: Object

μœ„μ˜ μ˜ˆμ‹œμ—μ„œ μ•Œ 수 μžˆλ“― [Prototype] 내에 μ •μ˜κ°€ λ˜μ–΄ μžˆλ‹€.

 

이에 λŒ€ν•œ λ‚΄μš©μ€ 좔후에 μžμ„Ένžˆ λ‹€λ£° μ˜ˆμ •μ΄λ‹€!

 

 

2) λ‹€λ₯Έ λ°©μ‹μœΌλ‘œ λ§Œλ“  κ°μ²΄λ“€κ³Όμ˜ 비ꡐ

μœ„μ—μ„œ μ–ΈκΈ‰ν•œλŒ€λ‘œ μƒμ„±μžν•¨μˆ˜λ‘œ λ§Œλ“  κ°μ²΄λŠ” λ‹€λ₯Έ 것듀과 λ‹€λ₯΄λ‹€.

그것을 직접 비ꡐ해보며 μ•Œμ•„λ³΄μž!

 

// μƒμ„±μž ν•¨μˆ˜
function Player(name, job){
  this.name = name;
  this.job = job;
  this.info = function () {
    return `μ†Œν™˜μ‚¬λͺ… : ${this.name} | 직업ꡰ : ${this.job}`;
  }
}

// 객체 λ°˜ν™˜ ν•¨μˆ˜
function createPlayer(name, job){
  return {
    name, job,
    info (){
      return `μ†Œν™˜μ‚¬λͺ… : ${this.name} | 직업ꡰ : ${this.job}`;
    }
  }
}

 

3κ°€μ§€ λ°©λ²•μœΌλ‘œ λ§Œλ“  객체듀을 λΉ„κ΅ν•΄λ³΄μž.

μƒμ„±μž ν•¨μˆ˜, 객체 λ°˜ν™˜  ν•¨μˆ˜, 객체 λ¦¬ν„°λŸ΄ 각각의 λ°©μ‹μœΌλ‘œ 생성해보면 μ•„λž˜μ™€ κ°™λ‹€.

// 1. μƒμ„±μž ν•¨μˆ˜ 이용
const player1 = new Player('Kassid', '전사');

// 2. 객체 λ°˜ν™˜ ν•¨μˆ˜ 이용
const player2 = createPlayer('Kassid', '전사');

// 3. 객체 λ¦¬ν„°λŸ΄ 방식
const player3 = {
  name : 'Kassid',
  job : '전사',
  introduce : function () {
    return `μ†Œν™˜μ‚¬λͺ… : ${this.name} | 직업ꡰ : ${this.job}`;
  }
}

 

console.log(player1);
console.log(player2);
console.log(player3);

μœ„μ˜ κ²°κ³Ό 화면을 보면 μ•Œ 수 μžˆλ“―μ΄

였직 μƒμ„±μžλ‘œ μƒμ„±ν•œ 객체만 닀름을 μ•Œ 수 μžˆλ‹€.

 

μ΄λŠ” logμ—μ„œ ν‘œμ‹œν•˜λŠ” κΈ°λŠ₯이고

객체 prototype의 constructorλ₯Ό μ‚΄νŽ΄λ³΄μ•„λ„ λ‹€λ₯Έ 것을 μ•Œ 수 μžˆλ‹€.

μƒμ„±μž ν•¨μˆ˜λ‘œ λ§Œλ“  객체
λ‹€λ₯Έ λ°©λ²•μœΌλ‘œ λ§Œλ“  객체

 

이λ₯Ό ν†΅ν•΄μ„œ μƒμ„±μžλ‘œ μƒμ„±ν•œ μΈμŠ€ν„΄μŠ€μž„μ„ 확인할 수 μžˆλ‹€. 

 

λ˜ν•œ

' instanceof 'μ—°μ‚°μžλ₯Ό μ΄μš©ν•΄λ„ ν•΄λ‹Ή 객체가 μƒμ„±μž ν•¨μˆ˜μ— μ˜ν•΄ λ§Œλ“€μ–΄μ‘ŒλŠ”μ§€λ₯Ό 확인할 수 μžˆλ‹€.

console.log(player1 instanceof Player);
console.log(player2 instanceof Player);
console.log(player3 instanceof Player);

>>> true
>>> false
>>> false

 

 

3. μƒμ„±μž ν•¨μˆ˜ 자체의 ν•„λ“œμ™€ ν•¨μˆ˜

// μƒμ„±μž ν•¨μˆ˜
function Player(name, job){
  this.name = name;
  this.job = job;
  this.info = function () {
    return `μ†Œν™˜μ‚¬λͺ… : ${this.name} | 직업ꡰ : ${this.job}`;
  }
}

// μƒμ„±μž μžμ²΄μ— ν”„λ‘œνΌν‹° μΆ”κ°€
Player.age = '23'
Player.attack = function(){
  return '곡격!';
}

 

μœ„μ™€ 같이 μƒμ„±μž ν•¨μˆ˜ μžμ²΄μ— μƒˆλ‘œμš΄ ν”„λ‘œνΌν‹°λ₯Ό μΆ”κ°€ν•œλ‹€.

μ΄λŸ¬ν•œ 방법을 μ‚¬μš©ν•œλ‹€λ©΄ μ–΄λ–€ 점이 λ‹€λ₯ΌκΉŒ?

 

 

λ¨Όμ € μƒμ„±μž ν•¨μˆ˜ μžμ²΄μ—λ„ 점 μ—°μ‚°μžλ₯Ό μ΄μš©ν•˜μ—¬ μ ‘κ·Όν•  수 μžˆλ‹€.

// μƒμ„±μž ν•¨μˆ˜ μžμ²΄μ— μ ‘κ·Όν•˜κΈ°
console.log(Player.attack());

>>> 곡격!

 

μ΄λ²ˆμ—” μƒμ„±μž ν•¨μˆ˜μ˜ μΈμŠ€ν„΄μŠ€λ₯Ό μƒμ„±ν•œ ν›„ ν•΄λ‹Ή ν•¨μˆ˜μ— μ ‘κ·Όν•΄λ³΄μž.

const player1 = new Player('Sally', 'ꢁ수');

// 일반 ν”„λ‘œνΌν‹°μ™€ ν”„λ‘œν† ν† μž…μ—μ„œ μƒμ„±ν•œ ν•¨μˆ˜ 각각 μ ‘κ·Ό
console.log(player1.info());
console.log(player1.attack());

>>> μ†Œν™˜μ‚¬λͺ… : Sally | 직업ꡰ : ꢁ수
>>> Uncaught TypeError: player1.attack is not a function

이처럼 기쑴의 일반 ν”„λ‘œνΌν‹° ν•¨μˆ˜μ—λŠ” 무리없이 접근이 κ°€λŠ₯ν•˜μ§€λ§Œ

ν”„λ‘œν† νƒ€μž…μ„ μ΄μš©ν•˜μ—¬ μƒˆλ‘œ μΆ”κ°€ν•œ ν”„λ‘œνΌν‹°λŠ” 접근이 λΆˆκ°€ν•˜λ‹€.

 

μ΄λŸ¬ν•œ 방식은 μƒμ„±ν•œ μΈμŠ€ν„΄μŠ€λ“€μ΄ μ•„λ‹Œ

μƒμ„±μž ν•¨μˆ˜ μžμ²΄μ— ν•„μš”ν•œ κΈ°λŠ₯을 λ§Œλ“€λ•Œ 주둜 μ‚¬μš©λœλ‹€.

 

 

4. new μ—°μ‚°μž μ‚¬μš©ν•˜μ§€ μ•ŠλŠ” 것 λ°©μ§€ν•˜κΈ°!

생성사 ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•  λ•Œ μœ„μ—μ„œ λ‹€λ€˜λ˜ κ²ƒμ²˜λŸΌ new μ—°μ‚°μžλ₯Ό κΌ­ μ΄μš©ν•΄μ•Όν•œλ‹€.

λ§Œμ•½ μ‚¬μš©ν•˜μ§€ μ•ŠλŠ” 경우 undefinedλ₯Ό λ°˜ν™˜ν•œλ‹€.

 

ν•˜μ§€λ§Œ 이λ₯Ό κ°œλ°œμžκ°€ μ„€κ³„μ‹œμ— λ°©μ§€ν•  수 μžˆλŠ” 방법이 μžˆλ‹€.

λ°”λ‘œ new.target을 μ΄μš©ν•˜λŠ” 것이닀!

 

new.taget은 μƒμ„±μž ν•¨μˆ˜λ‘œ λ§Œλ“€μ–΄μ§„ 객체인 κ²½μš°μ— 항상 ν•¨κ»˜ μƒμ„±λœλ‹€.

λ”°λΌμ„œ μ΄κ²ƒμ˜ 유무λ₯Ό 확인 ν›„

없을 경우 new μ—°μ‚°μžλ₯Ό 뢙인 μƒμ„±μž ν•¨μˆ˜λ₯Ό μž¬κ·€ν˜ΈμΆœν•˜λ©΄ λœλ‹€.

 

μ˜ˆμ‹œ)

// μƒμ„±μž ν•¨μˆ˜
function Player(name, job){
  this.name = name;
  this.job = job;
  this.info = function () {
    return `μ†Œν™˜μ‚¬λͺ… : ${this.name} | 직업ꡰ : ${this.job}`;
  }
  
  if (!new.target){
    return new Player(name, job);
  }
}

const p1 = new Player('Kassid', '전사');
const p2 = Player('Kassid', '전사');

μœ„μ˜ μ˜ˆμ‹œμ—μ„œ p1은 μƒμ„±μž ν•¨μˆ˜λ₯Ό newμ—°μ‚°μžμ™€ ν•¨κ»˜ μ΄μš©ν•˜μ˜€κ³  

p2λŠ” κ·Έλ ‡μ§€ μ•Šμ€ 잘λͺ»λœ μ˜ˆμ‹œμ΄λ‹€.

 

이λ₯Ό ν™•μΈν•΄λ³΄μž!

console.log(p1);
console.log(p2);

>>> Player {name: 'Kassid', job: '전사', info: Ζ’}
>>> Player {name: 'Kassid', job: '전사', info: Ζ’}

잘λͺ» μ‚¬μš©ν•œ p2 μ—­μ‹œ undefinedκ°€ μ•„λ‹Œ μƒμ„±μž ν•¨μˆ˜λ‘œ λ§Œλ“  객체가 μ •μƒμ μœΌλ‘œ λ“€μ–΄κ°„ λͺ¨μŠ΅μ΄λ‹€.

 

λŒ“κΈ€