[πŸ“– λͺ¨λ˜ μžλ°”μŠ€ν¬λ¦½νŠΈ λ”₯λ‹€μ΄λΈŒ] 17μž₯. μƒμ„±μž ν•¨μˆ˜μ— μ˜ν•œ 객체 생성

λ…Έμ˜μ™„Β·2023λ…„ 10μ›” 31일
0

JavaScript(Deep Dive)

λͺ©λ‘ 보기
12/23
post-thumbnail

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

βœ” 객체 생성 방식에 객체 λ¦¬ν„°λŸ΄μ— μ˜ν•œ 생성 방식도 μžˆμ§€λ§Œ, λ‹€μ–‘ν•œ λ‹€λ₯Έ 방식도 μžˆλ‹€.
βœ” λ‹€μ–‘ν•œ 객체 생성 방식 쀑에 μƒμ„±μž ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•˜μ—¬ 객체λ₯Ό μƒμ„±ν•˜λŠ” 방식을 μ‚΄νŽ΄λ³΄κ³  객체 λ¦¬ν„°λŸ΄ 객체 생성 방식과 μƒμ„±μž ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•˜μ—¬ 객체λ₯Ό μƒμ„±ν•˜λŠ” λ°©μ‹μ˜ μž₯단점을 μ•Œμ•„λ³Έλ‹€.

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

new μ—°μ‚°μž 와 ν•¨κ»˜ Object μƒμ„±μž ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜λ©΄ 빈 객체λ₯Ό μƒμ„±ν•˜μ—¬ λ°˜ν™˜. 빈 객체λ₯Ό μƒμ„±ν•œ 이후 ν”„λ‘œνΌν‹° λ˜λŠ” λ©”μ„œλ“œλ₯Ό μΆ”κ°€ν•˜μ—¬ 객체 μ™„μ„±

μžλ°”μŠ€ν¬λ¦½νŠΈλŠ” Object μƒμ„±μž ν•¨μˆ˜ 이외에도 String Number Boolean Function Array Date RegExp Promiseλ“±μ˜ 빌트인 μƒμ„±μž ν•¨μˆ˜λ₯Ό μ œκ³΅ν•œλ‹€.

// 빈 객체의 생성
const person = new Object();

// ν”„λ‘œνΌν‹°μΆ”κ°€
person.name = "noh";
person.sayHello = function() {
	console.log("Hi! My name is" + this.name);
};

console.log(person) // {name: "noh", sayHello : f}
person.sayHello(); // Hi! My name is noh
// String μƒμ„±μž ν•¨μˆ˜μ— μ˜ν•œ String 객체 생성
const strObj = new String("Noh");
console.log(typeof strObj) // object
console.log(strObj) // String {"noh"}

// Number μƒμ„±μž ν•¨μˆ˜μ— μ˜ν•œ Number 객체 생성
const numObj = new Number(123);
console.log(typeof numObj) // object
console.log(numObj) // Number {123}

// Boolean μƒμ„±μž ν•¨μˆ˜μ— μ˜ν•œ Boolean 객체 μƒˆμ„±
const boolObj = new Boolean(true);
console.log(typeof boolObj); // object
console.log(boolObj); //Boolean {true}

// Function μƒμ„±μž ν•¨μˆ˜μ— μ˜ν•œ Function 객체(ν•¨μˆ˜) μƒˆμ„±
const func = new Function ('x', "return x * x" );
console.log(typeof func);
console.dir(func);

// Array μƒμ„±μž ν•¨μˆ˜μ— μ˜ν•œ Array 객체(λ°°μ—΄) 생성
const arr = new Array(1,2,3)
console.log(typeof arr); // object
console.log(arr);

// RegExp μƒμ„±μž ν•¨μˆ˜μ— μ˜ν•œ RegExp 객체(μ •κ·œ ν‘œν˜„μ‹) 생성
const regExp = new RegExp(/ab+c/i);
console.log(typeof regExp); // object
console.log(regExp); // /ab+c/i

// Date μƒμ„±μž ν•¨μˆ˜μ— μ˜ν•œ Date 객체 생성
console.log(typeof date); // object
console.log(date) /

πŸ’‘ μƒμ„±μž ν•¨μˆ˜λž€?

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

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

2-1. 객체 λ¦¬ν„°λŸ΄μ— μ˜ν•œ 객체 생성 λ°©μ‹μ˜ 문제점

객체 λ¦¬ν„°λŸ΄μ— μ˜ν•œ 객체 생성 방식은 직관적이고 κ°„νŽΈν•˜μ§€λ§Œ 단 ν•˜λ‚˜μ˜ 객체만 μƒμ„±ν•œλ‹€. λ”°λΌμ„œ λ™μΌν•œ ν”„λ‘œνΌν‹°λ₯Ό κ°–λŠ” 객체λ₯Ό μ—¬λŸ¬κ°œ μƒˆμ„±ν•΄μ•Ό ν•˜λŠ” 경우 λΉ„νš¨μœ¨μ μ΄λ‹€.

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

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

const circle2 = {
	radius: 10,
  	getDiameter() { // 객체 λ©”μ„œλ“œ function μƒλž΅κ°€λŠ₯ ν”„λ‘œνΌν‹°ν‚€ : getDiameter
      	return 2 * this.radius;
    }
};

console.log(circle2.getDiameter());

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

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

// μƒμ„±μž ν•¨μˆ˜
function Circle(radius) {
  // μƒμ„±μž ν•¨μˆ˜ λ‚΄λΆ€μ˜ thisλŠ” μƒμ„±μž ν•¨μˆ˜κ°€ 생성할 μΈμŠ€ν„΄μŠ€λ₯Ό 가리킨닀.
  this.radius = radius;
  this.getDiameter = function () {
		return 2 * this.radius;
  };
}

console.log(new Circle(5));

const circle1 = new Circle(5);
const circle2 = new Circle(10);

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

μƒμ„±μž ν•¨μˆ˜λŠ” 이름 κ·ΈλŒ€λ‘œ 객체(μΈμŠ€ν„΄μŠ€)λ₯Ό μƒμ„±ν•˜λŠ” ν•¨μˆ˜ new μ—°μ‚°μžμ™€ ν•¨κ»˜ ν˜ΈμΆœν•˜λ©΄ ν•΄λ‹Ή ν•¨μˆ˜λŠ” μƒμ„±μž ν•¨μˆ˜λ‘œ λ™μž‘ λ§Œμ•½ new μ—°μ‚°μžμ™€ ν•¨κ»˜ μƒμ„±μž ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜μ§€ μ•ŠμœΌλ©΄ μƒμ„±μž ν•¨μˆ˜κ°€ μ•„λ‹ˆλΌ μΌλ°˜ν•¨μˆ˜λ‘œ λ™μž‘.

// new μ—°μ‚°μžμ™€ ν•¨κ»˜ ν˜ΈμΆœν•˜μ§€ μ•ŠμœΌλ©΄ μƒμ„±μž ν•¨μˆ˜λ‘œ λ™μž‘ν•˜μ§€ μ•ŠλŠ”λ‹€.
// 즉, 일반 ν•¨μˆ˜λ‘œ ν˜ΈμΆœλœλ‹€.
const circle3 = Circle(15);

// 일반 ν•¨μˆ˜λ‘œμ„œ 호좜된 Circle은 λ°˜ν™˜λ¬Έμ΄ μ—†μœΌλ―€λ‘œ undefinedλ₯Ό λ°˜ν™˜.
console.log(circle3); // undefined

// 일반 ν•¨μˆ˜λ‘œμ„œ 호좜된 Circleλ‚΄μ˜ thisλŠ” μ „μ—­ 객체λ₯Ό 가리킨닀.
console.log(radius); // 15

2-3. μƒμ„±μž ν•¨μˆ˜μ˜ μΈμŠ€ν„΄μŠ€ 생성과정

μƒμ„±μž ν•¨μˆ˜μ˜ 역할은 ν”„λ‘œνΌν‹° ꡬ쑰가 λ™μΌν•œ μΈμŠ€ν„΄μŠ€λ₯Ό μƒμ„±ν•˜κΈ° μœ„ν•œ ν…œν”Œλ¦Ώ(클래슀)μœΌλ‘œμ„œ λ™μž‘ν•˜μ—¬ μΈμŠ€ν„΄μŠ€λ₯Ό μƒμ„±ν•˜λŠ” 것과 μƒμ„±λœ μΈμŠ¨ν„΄μŠ€λ₯Ό μ΄ˆκΈ°ν™”(μΈμŠ€ν„΄μŠ€ ν”„λ‘œνΌν‹° μΆ”κ°€ 및 μ΄ˆκΈ°ν™” ν• λ‹Ή)ν•˜λŠ” 것이닀.

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

μƒμ„±μž ν•¨μˆ˜ λ‚΄λΆ€μ—μ„œ return 문을 λ°˜λ“œμ‹œ μƒλž΅ν•΄μ•Ό ν•œλ‹€.

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

  • μ•”λ¬΅μ μœΌλ‘œ 빈 객체 생성. 그리고 μ•”λ¬΅μ μœΌλ‘œ μƒˆμ„±λœ 빈 객체, 즉 μΈμŠ€ν„΄μŠ€λŠ” this에 바인딩 λœλ‹€.

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

  • μƒμ„±μž ν•¨μˆ˜μ— κΈ°μˆ λ˜μ–΄ μžˆλŠ” μ½”λ“œκ°€ ν•œ 쀄씩 μ‹€ν–‰λ˜μ–΄ this에 바인딩 λ˜μ–΄μžˆλŠ” μΈμŠ€ν„΄μŠ€λ₯Ό μ΄ˆκΈ°ν™”

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

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

  • 즉, this에 λ°”μΈλ”©λ˜μ–΄ μžˆλŠ” μΈμŠ€ν„΄μŠ€μ— ν”„λ‘œνΌν‹°λ‚˜ λ©”μ„œλ“œλ₯Ό μΆ”κ°€ν•˜κ³  μƒμ„±μž ν•¨μˆ˜κ°€ 인수둜 전달받은 μ΄ˆκΈ°κ°’μ„ μΈμŠ€ν„΄μŠ€ ν”„λ‘œνΌν‹°μ— ν• λ‹Ήν•˜μ—¬ μ΄ˆκΈ°ν™”ν•˜κ±°λ‚˜ 고정값을 ν• λ‹Ήν•œλ‹€.

πŸ’‘ λ°”μΈλ”©μ΄λž€?

λ°”μΈλ”©μ΄λž€ μ‹λ³„μžμ™€ 값을 μ—°κ²°ν•˜λŠ” 과정을 의미 예λ₯Ό λ“€μ–΄, λ³€μˆ˜ 선언은 λ³€μˆ˜μ΄λ¦„(μ‹λ³„μž)κ³Ό ν™•λ³΄λœ λ©”λͺ¨λ¦¬ κ³΅κ°„μ˜ μ£Όμ†Œλ₯Ό λ°”μΈλ”©ν•˜λŠ” 것이닀.

this 바인딩은 this(ν‚€μ›Œλ“œλ‘œ λΆ„λ₯˜λ˜μ§€λ§Œ μ‹λ³„μž 역할을 ν•œλ‹€)와 thisκ°€ 가리킬 객체λ₯Ό 바인딩 ν•˜λŠ” 것이닀.

πŸ’‘ μ΄ˆκΈ°ν™”λž€?

μ΄ˆκΈ°ν™”(initialization)λž€ ν”„λ‘œκ·Έλž˜λ°μ—μ„œ 데이터 μ˜€λΈŒμ νŠΈλ‚˜ λ³€μˆ˜μ˜ μ΄ˆκΉƒκ°’ 할당을 의미 즉, 첫 λ³€μˆ˜λ₯Ό μ„ μ–Έκ³Ό λ™μ‹œμ— 할당을 ν•œ 것을 μ΄ˆκΈ°ν™”λΌκ³  ν•˜λ©° 이후 =을 μ‚¬μš©ν•œ 것은 할당이라 λΆ€λ₯Έλ‹€.

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

βœ” λ§Œμ•½ thisκ°€ μ•„λ‹Œ λ‹€λ₯Έ 객체λ₯Ό λͺ…μ‹μ μœΌλ‘œ λ°˜ν™˜ν•˜λ©΄ thisκ°€ λ°˜ν™˜λ˜μ§€ λͺ»ν•˜κ³  return문에 λͺ…μ‹œν•œ 객체가 λ°˜ν™˜λœλ‹€.

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

// μΈμŠ€ν„΄μŠ€ 생성. Circle μƒμ„±μž ν•¨μˆ˜λŠ” λͺ…μ‹œμ μœΌλ‘œ λ°˜ν™˜ν•œ 객체λ₯Ό λ°˜ν™˜ν•œλ‹€.
const circle = new Circle(1);
console.log(circle); // {}
	

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

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

// μΈμŠ€ν„΄μŠ€ 생성. Circle μƒμ„±μž ν•¨μˆ˜λŠ” λͺ…μ‹œμ μœΌλ‘œ λ°˜ν™˜ν•œ 객체λ₯Ό λ°˜ν™˜ν•œλ‹€.
const circle = new Circle(1);
console.log(circle); // {radius: 1, getDiameter:f}

2-4. λ‚΄λΆ€ λ©”μ„œλ“œ [[Call]]κ³Ό [[Construct]]

ν•¨μˆ˜λŠ” 일반적인 ν•¨μˆ˜λ‘œμ„œ ν˜ΈμΆœν•  수 μžˆλŠ” 것은 λ¬Όλ‘  μƒμ„±μž ν•¨μˆ˜λ‘œμ„œ ν˜ΈμΆœν•  수 μžˆλ‹€.

ν•¨μˆ˜λŠ” κ°μ²΄μ΄λ―€λ‘œ μΌλ°˜κ°μ²΄μ™€ λ™μΌν•˜κ²Œ λ™μž‘ν•  수 μžˆλ‹€. ν•¨μˆ˜ κ°μ²΄λŠ” 일반 객체가 가지고 μžˆλŠ” λ‚΄λΆ€ 슬둯과 λ‚΄λΆ€ λ©”μ„œλ“œλ₯Ό λͺ¨λ‘ 가지고 있기 λ•Œλ¬Έ.

// ν•¨μˆ˜λŠ” 객체닀.
function foo() {}

// ν•¨μˆ˜λŠ” κ°μ²΄μ΄λ―€λ‘œ ν”„λ‘œνΌν‹°λ₯Ό μ†Œμœ ν•  수 μžˆλ‹€.
foo.prop = 10;

// ν•¨μˆ˜λŠ” κ°μ²΄μ΄λ―€λ‘œ λ©”μ„œλ“œλ₯Ό μ†Œμœ ν•  수 μžˆλ‹€.
foo.method = function () {
  console.log(this.prop);
  };

foo.method(); // 10

ν•¨μˆ˜λŠ” κ°μ²΄μ΄μ§€λ§Œ 일반 κ°μ²΄μ™€λŠ” 닀름 일반 κ°μ²΄λŠ” ν˜ΈμΆœν•  수 μ—†μ§€λ§Œ ν•¨μˆ˜λŠ” ν˜ΈμΆœν•  수 μžˆλ‹€ λ”°λΌμ„œ ν•¨μˆ˜ κ°μ²΄λŠ” 일반 객체가 가지고 μžˆλŠ” λ‚΄λΆ€ 슬둯과 λ‚΄λΆ€ λ©”μ„œλ“œλŠ” λ¬Όλ‘ , ν•¨μˆ˜λ‘œμ„œ λ™μž‘ν•™κΈ° μœ„ν•΄ ν•¨μˆ˜ κ°μ²΄λ§Œμ„ μœ„ν•œ [[Environment]], [[FormalParameter]]λ“±μ˜ λ‚΄λΆ€ 슬둝과 [[Call]], [[Construct]] 같은 λ‚΄λΆ€ λ©”μ„œλ“œλ₯Ό μΆ”κ°€λ‘œ μ§€λ‹ˆκ³  μžˆλ‹€.

ν•¨μˆ˜κ°€ 일반 ν•¨μˆ˜λ‘œ 호좜되면 ν•¨μˆ˜ 객체의 λ‚΄λΆ€ λ©”μ„œλ“œ [[Call]]이 호좜되고 new μ—°μ‚°μžμ™€ ν•¨κ»˜ μƒμ„±μž ν•¨μˆ˜λ‘œμ„œ 호좜되면 λ‚΄λΆ€ λ©”μ„œλ“œ [[Construct]]κ°€ ν˜ΈμΆœλœλ‹€.

function foo() {
 
// 일반적인 ν•¨μˆ˜λ‘œμ„œ 호좜: [[Call]]이 ν˜ΈμΆœλœλ‹€.
foo();
  
// μƒμ„±μž ν•¨μˆ˜λ‘œμ„œ 호좜: [[Construct]]κ°€ ν˜ΈμΆœλœλ‹€.
new foo();

λ‚΄λΆ€ λ©”μ„œλ“œ [[Call]]을 κ°–λŠ” ν•¨μˆ˜ 객체λ₯Ό callable λ‚΄λΆ€ λ©”μ„œλ“œ [[Construct]]λ₯Ό κ°–λŠ” ν•¨μˆ˜ 객체λ₯Ό constructor, [[Construct]]λ₯Ό 갖지 μ•ŠλŠ” ν•¨μˆ˜ 객체λ₯Ό non-constructor이라고 λΆ€λ₯Έλ‹€.

ν•¨μˆ˜ κ°μ²΄λŠ” λ°˜λ“œμ‹œ callable이어야 ν•œλ‹€. λ”°λΌμ„œ λͺ¨λ“  ν•¨μˆ˜ κ°μ²΄λŠ” λ‚΄λΆ€ λ©”μ„œλ“œ [[Call]]을 κ°–κ³  μžˆμœΌλ―€λ‘œ 호좜 ν•  수 있으며 λͺ¨λ“  ν•¨μˆ˜ 객체가 [[Construct]]λ₯Ό κ°–λŠ” 것은 μ•„λ‹ˆλ‹€. λ‹€μ‹œλ§ν•΄, constructor일 μˆ˜λ„ 있고 non-constructor일 μˆ˜λ„ μžˆλ‹€.

2-5. constructor와 non-constructor의 ꡬ뢄

μžλ°”μŠ€ν¬λ¦½νŠΈ 엔진은 ν•¨μˆ˜ μ •μ˜ 방식에 따라 constructor와 non-constructor둜 κ΅¬λΆ„ν•œλ‹€.

  • constructor: ν•¨μˆ˜ μ„ μ–Έλ¬Έ, ν•¨μˆ˜ ν‘œν˜„μ‹, 클래슀(ν΄λž˜μŠ€λ„ ν•¨μˆ˜)
  • non-constructor: λ©”μ„œλ“œ(ES6 λ©”μ„œλ“œ μΆ•μ•½ ν‘œν˜„), ν™”μ‚΄ν‘œ ν•¨μˆ˜
// 일반 ν•¨μˆ˜ μ •μ˜: ν•¨μˆ˜ μ„ μ–Έλ¬Έ, ν•¨μˆ˜ ν‘œν˜„μ‹
function foo() {}
const bar = function () {};
// ν”„λ‘œνΌν‹° x의 κ°’μœΌλ‘œ ν• λ‹Ήλœ 것은 일반 ν•¨μˆ˜λ‘œ μ •μ˜λœ ν•¨μˆ˜λ‹€. μ΄λŠ” λ©”μ„œλ“œλ‘œ μΈμ •ν•˜μ§€ μ•ŠλŠ”λ‹€.
const baz = {
  x: function () {}
};

// 일반 ν•¨μˆ˜λ‘œ μ •μ˜λœ ν•¨μˆ˜λ§Œμ΄ constructor이닀.
new foo();   // -> foo {}
new bar();   // -> bar {}
new baz.x(); // -> x {}

// ν™”μ‚΄ν‘œ ν•¨μˆ˜ μ •μ˜
const arrow = () => {};

new arrow(); // TypeError: arrow is not a constructor

// λ©”μ„œλ“œ μ •μ˜: ES6의 λ©”μ„œλ“œ μΆ•μ•½ ν‘œν˜„λ§Œμ„ λ©”μ„œλ“œλ‘œ μΈμ •ν•œλ‹€.
const obj = {
  x() {}
};

new obj.x(); // TypeError: obj.x is not a constructor

2-6. new μ—°μ‚°μž

μΌλ°˜ν•¨μˆ˜μ™€ μƒμ„±μž ν•¨μˆ˜μ— νŠΉλ³„ν•œ ν˜•μ‹μ  μ°¨μ΄λŠ” μ—†λ‹€.

일반 ν•¨μˆ˜λ₯Ό μ •μ˜ν•΄μ„œ new μ—°μ‚°μžλ₯Ό 톡해 ν•¨μˆ˜ ν˜ΈμΆœν•˜λ©΄ μƒμ„±μž ν•¨μˆ˜λ‘œ λ™μž‘ν•˜κ³ , μƒμ„±μž ν•¨μˆ˜λ₯Ό μ •μ˜ν•΄μ„œ new μ—°μ‚°μž 없이 ν˜ΈμΆœν•˜λ©΄ 일반 ν•¨μˆ˜λ‘œ λ™μž‘ν•œλ‹€.

μƒμ„±μž ν•¨μˆ˜λŠ” 일반적으둜 첫 문자λ₯Ό λŒ€λ¬Έμžλ‘œ ν•˜μ—¬ 일반 ν•¨μˆ˜μ™€ ꡬ별할 수 μžˆλ„λ‘ ν•œλ‹€.

2-7. new.target

new μ—°μ‚°μž 없이 ν˜ΈμΆœλ˜λŠ” 것을 λ°©μ§€ν•˜κΈ° μœ„ν•΄ ES6μ—μ„œ new.target을 지원.

new.targetμ—°μ‚°μžλŠ” this와 μœ μ‚¬ν•˜κ²Œ constructor인 λͺ¨λ“  ν•¨μˆ˜ λ‚΄λΆ€μ—μ„œ 암묡적인 μ§€μ—­λ³€μˆ˜μ™€ 같이 μ‚¬μš©λ˜λ©° 메타 ν”„λ‘œνΌν‹°λΌκ³  λΆ€λ₯Έλ‹€.(IEλŠ” μ§€μ›μ•ˆν•¨)

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

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

  this.radius = radius;
  this.getDiameter = function () {
    return 2 * this.radius;
  };
}

// new μ—°μ‚°μž 없이 μƒμ„±μž ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜μ—¬λ„ new.target을 톡해 μƒμ„±μž ν•¨μˆ˜λ‘œμ„œ ν˜ΈμΆœλœλ‹€.
const circle = Circle(5);
console.log(circle.getDiameter());

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

  • μŠ€μ½”ν”„ 세이프 μƒμ •μž νŒ¨ν„΄scope-safe constructor new.target을 μ‚¬μš©ν•  수 μ—†λŠ” 상황이라면 μŠ€μ½”ν”„ 세이프 μƒμ„±μž νŒ¨ν„΄μ„ μ‚¬μš©ν•  수 μžˆλ‹€. instanceof μ—°μ‚°μžλ₯Ό ν™œμš©ν•œλ‹€.
// Scope-Safe Constructor Pattern
function Circle(radius) {
  // μƒμ„±μž ν•¨μˆ˜κ°€ new μ—°μ‚°μžμ™€ ν•¨κ»˜ 호좜되면 ν•¨μˆ˜μ˜ μ„ λ‘μ—μ„œ 빈 객체λ₯Ό μƒμ„±ν•˜κ³ 
  // this에 λ°”μΈλ”©ν•œλ‹€. μ΄λ•Œ this와 Circle은 ν”„λ‘œν† νƒ€μž…μ— μ˜ν•΄ μ—°κ²°λœλ‹€.

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

  this.radius = radius;
  this.getDiameter = function () {
    return 2 * this.radius;
  };
}

// new μ—°μ‚°μž 없이 μƒμ„±μž ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜μ—¬λ„ μƒμ„±μž ν•¨μˆ˜λ‘œμ„œ ν˜ΈμΆœλœλ‹€.
const circle = Circle(5);
console.log(circle.getDiameter()); // 10

πŸ’‘ 빌트인 μƒμ„±μž ν•¨μˆ˜(Object, String, Number, Boolean, Function, Array, Date, RegExp, Promise λ“±) new μ—°μ‚°μž

βœ” Object와 Functionν•¨μˆ˜λŠ” new μ—°μ‚°μž 없이 ν˜ΈμΆœν•΄λ„ new μ—°μ‚°μžμ™€ ν•¨κ»˜ ν˜ΈμΆœν•œ κ²½μš°μ™€ λ™μΌν•˜κ²Œ λ™μž‘

let obj = new Object();
console.log(obj); // {}

obj = Object();
console.log(obj); // {}

let f = new Function('x', 'return x ** x');
console.log(f); // Ζ’ anonymous(x) { return x ** x }

f = Function('x', 'return x ** x');
console.log(f); // Ζ’ anonymous(x) { return x ** x }

βœ” String, Number, Boolean은 newμ—°μ‚°μžμ™€ ν•¨κ»˜ ν˜ΈμΆœν–ˆμ„ λ•Œ 객체λ₯Ό μƒμ„±ν•˜μ—¬ λ°˜ν™˜ν•˜μ§€λ§Œ, newμ—°μ‚°μž 없이 ν˜ΈμΆœν•˜λ©΄ λ¬Έμžμ—΄, 숫자, λΆˆλ¦¬μ–Έ μ›μ‹œ 값을 λ°˜ν™˜ν•œλ‹€. 이λ₯Ό 톡해 데이터 νƒ€μž… λ³€ν™˜ν•˜κΈ°λ„ 함.

const str = String(123);
console.log(str, typeof str); // 123 string

const num = Number('123');
console.log(num, typeof num); // 123 number

const bool = Boolean('true');
console.log(bool, typeof bool); // true boolean

0개의 λŒ“κΈ€