๐ก ์์ฑ์ ํจ์์ ์ํ ๊ฐ์ฒด ์์ฑ
- ๋ค์ํ ๊ฐ์ฒด ์์ฑ ๋ฐฉ์ ์ค์์ ์์ฑ์ ํจ์๋ฅผ ์ฌ์ฉํ์ฌ ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ ๋ฐฉ์
- ๊ฐ์ฒด ๋ฆฌํฐ๋ด์ ์ฌ์ฉํ์ฌ ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ ๋ฐฉ์๊ณผ ์์ฑ์ ํจ์๋ฅผ ์ฌ์ฉํ์ฌ ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ ๋ฐฉ์๊ณผ์ ์ฅ๋จ์
1. Object ์์ฑ์ ํจ์
new ์ฐ์ฐ์์ ํจ๊ป Object ์์ฑ์ ํจ์๋ฅผ ํธ์ถํ๋ฉด ๋น ๊ฐ์ฒด๋ฅผ ์์ฑํ์ฌ ๋ฐํํ๋ค.
๋น ๊ฐ์ฒด๋ฅผ ์์ฑํ ์ดํ ํ๋กํผํฐ ๋๋ ๋ฉ์๋๋ฅผ ์ถ๊ฐํ์ฌ ๊ฐ์ฒด๋ฅผ ์์ฑํ ์ ์๋ค.
// ๋น ๊ฐ์ฒด์ ์์ฑ
const person = new Object();
// ํ๋กํผํฐ ์ถ๊ฐ
person.name = 'Lee';
person.sayHello = function () {
console.log('Hi! My name is ' this.name);
};
console.log(person); // {name: "Lee", sayHello: f}
person.sayHello(); // Hi! My name is Lee
โ๏ธ ์์ฑ์ ํจ์ (constructor): new ์ฐ์ฐ์์ ํจ๊ป ํธ์ถํ์ฌ ๊ฐ์ฒด(์ธ์คํด์ค)๋ฅผ ์์ฑํ๋ ํจ์
โ๏ธ ์ธ์คํด์ค (instance): ์์ฑ์ ํจ์์ ์ํด ์์ฑ๋ ๊ฐ์ฒด
โข ์๋ฐ์คํฌ๋ฆฝํธ๋ Object ์์ฑ์ ํจ์ ์ด์ธ์๋ String, Number, Boolean, Function, Array, Date, RegExp, Promise ๋ฑ ๋นํธ์ธ ์์ฑ์ ํจ์๋ฅผ ์ ๊ณตํ๋ค.
๋ฐ๋์ Object ์์ฑ์ ํจ์๋ฅผ ์ฌ์ฉํด ๋น ๊ฐ์ฒด๋ฅผ ์์ฑํด์ผ ํ๋ ๊ฒ์ ์๋๋ค. ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ ๋ฐฉ๋ฒ์ ๊ฐ์ฒด ๋ฆฌํฐ๋ด์ ์ฌ์ฉํ๋ ๊ฒ์ด ๋ ๊ฐํธํ๋ค.
2. ์์ฑ์ ํจ์
2-1. ๊ฐ์ฒด ๋ฆฌํฐ๋ด์ ์ํ ๊ฐ์ฒด ์์ฑ ๋ฐฉ์์ ๋ฌธ์ ์
๊ฐ์ฒด ๋ฆฌํฐ๋ด์ ์ํ ๊ฐ์ฒด ์์ฑ ๋ฐฉ์์ ์ง๊ด์ ์ด๊ณ ํธํ๋ค. ํ์ง๋ง ๊ฐ์ฒด ๋ฆฌํฐ๋ด์ ์ํ ๊ฐ์ฒด ์์ฑ ๋ฐฉ์์ ๋จ ํ๋์ ๊ฐ์ฒด๋ง ์์ฑํ๋ค.
๋ฐ๋ผ์ ๋์ผํ ํ๋กํผํฐ๋ฅผ ๊ฐ๋ ๊ฐ์ฒด๋ฅผ ์ฌ๋ฌ ๊ฐ ์์ฑํด์ผ ํ๋ ๊ฒฝ์ฐ ๋งค๋ฒ ๊ฐ์ ํ๋กํผํฐ๋ฅผ ๊ธฐ์ ํด์ผ ํ๊ธฐ ๋๋ฌธ์ ๋นํจ์จ์ ์ด๋ค.
โ๏ธ ๊ฐ์ฒด๋ ํ๋กํผํฐ๋ฅผ ํตํด ๊ฐ์ฒด ๊ณ ์ ์ ์ํ๋ฅผ ํํํ๋ค.
โ๏ธ ๊ฐ์ฒด๋ ๋ฉ์๋๋ฅผ ํตํด ์ํ ๋ฐ์ดํฐ์ธ ํ๋กํผํฐ๋ฅผ ์ฐธ์กฐํ๊ณ ์กฐ์ํ๋ ๋์์ ํํํ๋ค.
๋ฐ๋ผ์, ํ๋กํผํฐ๋ ๊ฐ์ฒด๋ง๋ค ํ๋กํผํฐ ๊ฐ์ด ๋ค๋ฅผ ์ ์์ง๋ง ๋ฉ์๋๋ ๋ด์ฉ์ด ๋์ผํ ๊ฒฝ์ฐ๊ฐ ์ผ๋ฐ์ ์ด๋ค.
2-2. ์์ฑ์ ํจ์์ ์ํ ๊ฐ์ฒด ์์ฑ ๋ฐฉ์์ ์ฅ์
์์ฑ์ ํจ์์ ์ํ ๊ฐ์ฒด ์์ฑ ๋ฐฉ์์ ๋ง์น ๊ฐ์ฒด(์ธ์คํด์ค)๋ฅผ ์์ฑํ๊ธฐ ์ํ ํ ํ๋ฆฟ(ํด๋์ค)์ฒ๋ผ ์์ฑ์ ํจ์๋ฅผ ์ฌ์ฉํ์ฌ ํ๋กํผํฐ ๊ตฌ์กฐ๊ฐ ๋์ผํ ๊ฐ์ฒด ์ด๋ฌ ๊ฐ๋ฅผ ๊ฐํธํ๊ฒ ์์ฑํ ์ ์๋ค.
function Circle(radius) {
// ์์ฑ์ ํจ์ ๋ด๋ถ์ this๋ ์์ฑ์ ํจ์๊ฐ ์์ฑํ ์ธ์คํด์ค๋ฅผ ๊ฐ๋ฆฌํจ๋ค.
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 ์ฐ์ฐ์์ ํจ๊ป ํธ์ถํ๋ฉด ํด๋น ํจ์๋ ์์ฑ์ ํจ์๋ก ๋์ํ๋ค. ๋ง์ฝ new ์ฐ์ฐ์์ ํจ๊ป ์์ฑ์ ํจ์๋ฅผ ํธ์ถํ์ง ์์ผ๋ฉด ์์ฑ์ ํจ์๊ฐ ์๋๋ผ ์ผ๋ฐ ํจ์๋ก ๋์ํ๋ค.
const circle3 = Circle(15);
console.log(circle3); // undefined
// ์ผ๋ฐ ํจ์๋ก์ ํธ์ถ๋ Circle ๋ด์ this๋ ์ ์ญ ๊ฐ์ฒด๋ฅผ ๊ฐ๋ฆฌํจ๋ค.
console.log(radius); // 15
2-3. ์์ฑ์ ํจ์์ ์ธ์คํด์ค ์์ฑ ๊ณผ์
์์ฑ์ ํจ์์ ์ญํ ์ ํ๋กํผํฐ ๊ตฌ์กฐ๊ฐ ๋์ผํ ์ธ์คํด์ค๋ฅผ ์์ฑํ๊ธฐ ์ํ ํ ํ๋ฆฟ์ผ๋ก์ ๋์ํ์ฌ ์ธ์คํด์ค๋ฅผ ์์ฑํ๋ ๊ฒ๊ณผ ์์ฑ๋ ์ธ์คํด์ค๋ฅผ ์ด๊ธฐํ(์ธ์คํด์ค ํ๋กํผํฐ ์ถ๊ฐ ๋ฐ ์ด๊ธฐ๊ฐ ํ ๋น)ํ๋ ๊ฒ์ด๋ค.
์์ฑ์ ํจ์๊ฐ ์ธ์คํด์ค๋ฅผ ์์ฑํ๋ ๊ฒ์ ํ์์ด๊ณ , ์์ฑ๋ ์ธ์คํด์ค๋ฅผ ์ด๊ธฐํํ๋ ๊ฒ์ ์ต์ ์ด๋ค.
// ์์ฑ์ ํจ์
function Circle(radius) {
// ์ธ์คํด์ค ์ด๊ธฐํ
this.radius = radius;
this.getDiameter = function () {
return 2 * this.radius;
};
}
// ์ธ์คํด์ค ์์ฑ
const circle1 = new Circle(5);
์์ฑ์ ํจ์ ๋ด๋ถ์ ์ฝ๋์์ this์ ํ๋กํผํฐ๋ฅผ ์ถ๊ฐํ๊ณ ํ์์ ๋ฐ๋ผ ์ ๋ฌ๋ ์ธ์๋ฅผ ํ๋กํผํฐ์ ์ด๊ธฐ๊ฐ์ผ๋ก์ ํ ๋นํ์ฌ ์ธ์คํด์ค๋ฅผ ์ด๊ธฐํํ๋ค. ํ์ง๋ง ์ธ์คํด์ค๋ฅผ ์์ฑํ๊ณ ๋ฐํํ๋ ์ฝ๋๋ ๋ณด์ด์ง ์๋๋ค.
๐ก ์๋ฐ์คํฌ๋ฆฝํธ ์์ง์ ์๋ฌต์ ์ธ ์ฒ๋ฆฌ๋ฅผ ํตํด ์ธ์คํด์ค๋ฅผ ์์ฑํ๊ณ ๋ฐํํ๋ค. new ์ฐ์ฐ์์ ํจ๊ป ์์ฑ์ ํจ์๋ฅผ ํธ์ถํ๋ฉด ์๋ฐ์คํฌ๋ฆฝํธ ์์ง์ ๋ค์๊ณผ ๊ฐ์ ๊ณผ์ ์ ๊ฑฐ์ณ ์๋ฌต์ ์ผ๋ก ์ธ์คํด์ค๋ฅผ ์์ฑํ๊ณ ์ธ์คํด์ค๋ฅผ ์ด๊ธฐํํ ํ ์๋ฌต์ ์ผ๋ก ์ธ์คํด์ค๋ฅผ ๋ฐํํ๋ค.
1๏ธโฃ ์ธ์คํด์ค ์์ฑ๊ณผ this ๋ฐ์ธ๋ฉ
์๋ฌต์ ์ผ๋ก ๋น ๊ฐ์ฒด๊ฐ ์์ฑ๋๋ค.
์ด ๋น ๊ฐ์ฒด๊ฐ ๋ฐ๋ก ์์ฑ์ ํจ์๊ฐ ์์ฑํ ์ธ์คํด์ค์ด๋ค.
์ด ์ธ์คํด์ค๋ this์ ๋ฐ์ธ๋ฉ๋๋ค.
โ ์์ฑ์ ๋ด๋ถ ํจ์์ this๊ฐ ์์ฑ์ ํจ์๊ฐ ์์ฑํ ์ธ์คํด์ค๋ฅผ ๊ฐ๋ฆฌํค๋ ์ด์ ๊ฐ ๋ฐ๋ก ์ด๊ฒ์ด๋ค.
์ด ์ฒ๋ฆฌ๋ ํจ์ ๋ชธ์ฒด์ ์ฝ๋๊ฐ ํ ์ค์ฉ ์คํ๋๋ ๋ฐํ์ ์ด์ ์ ์คํ๋๋ค.
โ ๋ฐ์ธ๋ฉ (name binding) - ์๋ณ์์ ๊ฐ์ ์ฐ๊ฒฐํ๋ ๊ณผ์
ex) ๋ณ์ ์ ์ธ์ ๋ณ์ ์ด๋ฆ(์๋ณ์)๊ณผ ํ๋ณด๋ ๋ฉ๋ชจ๋ฆฌ ๊ณต๊ฐ์ ์ฃผ์๋ฅผ ๋ฐ์ธ๋ฉํ๋ ๊ฒ.
this ๋ฐ์ธ๋ฉ์ this(ํค์๋๋ก ๋ถ๋ฅ๋์ง๋ง ์๋ณ์ ์ญํ ์ ํจ.)์ this๊ฐ ๊ฐ๋ฆฌํฌ ๊ฐ์ฒด๋ฅผ ๋ฐ์ธ๋ฉํ๋ ๊ฒ์ด๋ค.
2๏ธโฃ ์ธ์คํด์ค ์ด๊ธฐํ
์์ฑ์ ํจ์์ ๊ธฐ์ ๋์ด ์๋ ์ฝ๋๊ฐ ํ ์ค์ฉ ์คํ๋์ด this์ ๋ฐ์ธ๋ฉ๋์ด ์๋ ์ธ์คํด์ค๋ฅผ ์ด๊ธฐํํ๋ค.
this์ ๋ฐ์ธ๋ฉ๋์ด ์๋ ์ธ์คํด์ค์ ํ๋กํผํฐ๋ ๋ฉ์๋๋ฅผ ์ถ๊ฐํ๊ณ ์์ฑ์ ํจ์๊ฐ ์ธ์๋ก ์ ๋ฌ๋ฐ์ ์ด๊ธฐ๊ฐ์ ์ธ์คํด์ค ํ๋กํผํฐ์ ํ ๋นํ์ฌ ์ด๊ธฐํํ๊ฑฐ๋ ๊ณ ์ ๊ฐ์ ํ ๋นํ๋ค.
3๏ธโฃย ์ธ์คํด์ค ๋ฐํ
์์ฑ์ ํจ์ ๋ด๋ถ์ ๋ชจ๋ ์ฒ๋ฆฌ๊ฐ ๋๋๋ฉด ์์ฑ๋ ์ธ์คํด์ค๊ฐ ๋ฐ์ธ๋ฉ๋ this๊ฐ ์๋ฌต์ ์ผ๋ก ๋ฐํ๋๋ค.
function Circle(radius) {
// 1๏ธโฃ ์๋ฌต์ ์ผ๋ก ์ธ์คํด์ค๊ฐ ์์ฑ๋๊ณ this์ ๋ฐ์ธ๋ฉ๋๋ค.
console.log(this); // Circle {}
// 2๏ธโฃ this์ ๋ฐ์ธ๋ฉ๋์ด ์๋ ์ธ์คํด์ค๋ฅผ ์ด๊ธฐํํ๋ค.
this.radius = radius;
this.getDiameter = function () {
return 2 * this.radius;
};
// 3๏ธโฃ ์์ฑ๋ ์ธ์คํด์ค๊ฐ ๋ฐ์ธ๋ฉ๋ this๊ฐ ์๋ฌต์ ์ผ๋ก ๋ฐํ๋๋ค.
}
// ์ธ์คํด์ค ์์ฑ. Circle ์์ฑ์ ํจ์๋ ์๋ฌต์ ์ผ๋ก this๋ฅผ ๋ฐํํ๋ค.
const circle = new Circle(1);
console.log(circle); // Circle { radius: 1, getDiameter: f }
์ ์ฝ๋์ 3๏ธโฃย ์์ ๋ง์ฝ ๋ช ์์ ์ผ๋ก ๊ฐ์ฒด๋ฅผ ๋ฐํํ๋ฉด this๊ฐ ๋ฐํ๋์ง ๋ชปํ๊ณ return ๋ฌธ์ ๋ช ์ํ ๊ฐ์ฒด๊ฐ ๋ฐํ๋์ง๋ง, ์์ ๊ฐ์ ๋ฐํํ๋ฉด ์์ ๊ฐ ๋ฐํ์ ๋ฌด์๋๊ณ ์๋ฌต์ ์ผ๋ก this๊ฐ ๋ฐํ๋๋ค.
2-4. ๋ด๋ถ ๋ฉ์๋ [[Call]]๊ณผ [[Construct]]
ํจ์ ์ ์ธ๋ฌธ ๋๋ ํจ์ ํํ์์ผ๋ก ์ ์ํ ํจ์๋ ์ผ๋ฐ์ ์ธ ํจ์๋ก์ ํธ์ถํ ์ ์๋ ๊ฒ์ ๋ฌผ๋ก ์์ฑ์ ํจ์๋ก์ ํธ์ถํ ์ ์๋ค.
์์ฑ์ ํจ์๋ก์ ํธ์ถํ๋ค๋ ๊ฒ์ new ์ฐ์ฐ์์ ํจ๊ป ํธ์ถํ์ฌ ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ ๊ฒ์ ์๋ฏธํ๋ค.
ํจ์๋ ๊ฐ์ฒด์ด๋ฏ๋ก ์ผ๋ฐ ๊ฐ์ฒด์ ๋์ผํ๊ฒ ๋์ํ ์ ์๋ค.
ํจ์ ๊ฐ์ฒด๋ ์ผ๋ฐ ๊ฐ์ฒด๊ฐ ๊ฐ์ง๊ณ ์๋ ๋ด๋ถ ์ฌ๋กฏ๊ณผ ๋ด๋ถ ๋ฉ์๋๋ฅผ ๋ชจ๋ ๊ฐ์ง๊ณ ์๊ธฐ ๋๋ฌธ์ด๋ค.
// ํจ์ == ๊ฐ์ฒด
function foo() {}
// ํจ์ == ๊ฐ์ฒด -> ํ๋กํผํฐ ์์ ๊ฐ๋ฅ
foo.prop = 10;
// ํจ์ === ๊ฐ์ฒด -> ๋ฉ์๋ ์์ ๊ฐ๋ฅ
foo.method = function () {
console.log(this.prop);
}
foo.method(); // 10
ํจ์๋ ๊ฐ์ฒด์ด์ง๋ง ์ผ๋ฐ ๊ฐ์ฒด์๋ ๋ค๋ฅด๋ค.
โ ์ผ๋ฐ ๊ฐ์ฒด๋ ํธ์ถํ ์ ์์ง๋ง ํจ์๋ ํธ์ถํ ์ ์๋ค.
ํจ์ ๊ฐ์ฒด๋ ์ผ๋ฐ ๊ฐ์ฒด๊ฐ ๊ฐ์ง๊ณ ์๋ ๋ด๋ถ ์ฌ๋กฏ, ๋ด๋ถ ๋ฉ์๋์ ๋ฌผ๋ก ํจ์๋ก์ ๋์ํ๊ธฐ ์ํด ํจ์ ๊ฐ์ฒด๋ง์ ์ํ [[Call]], [[Construct]] ๊ฐ์ ๋ด๋ถ ๋ฉ์๋๋ฅผ ์ถ๊ฐ๋ก ๊ฐ์ง๊ณ ์๋ค.
โ๏ธ ํจ์๊ฐ ์ผ๋ฐ ํจ์๋ก์ ํธ์ถ๋๋ฉด ํจ์ ๊ฐ์ฒด์ ๋ด๋ถ ๋ฉ์๋ [[Call]] ํธ์ถ
โ๏ธ new ์ฐ์ฐ์์ ํจ๊ป ์์ฑ์ ํจ์๋ก์ ํธ์ถ๋๋ฉด ๋ด๋ถ ๋ฉ์๋ [[Construct]] ํธ์ถ
function foo() {}
foo(); // [[Call]] ํธ์ถ
new foo(); // [[Construct]] ํธ์ถ
- callable: ํจ์ (ํธ์ถํ ์ ์๋ ๊ฐ์ฒด)
- constructor: ์์ฑ์ ํจ์๋ก์ ํธ์ถํ ์ ์๋ ํจ์
- non-constructor: ๊ฐ์ฒด๋ฅผ ์์ฑ์ ํจ์๋ก์ ํธ์ถํ ์ ์๋ ํจ์
ํธ์ถํ ์ ์๋ ๊ฐ์ฒด๋ ํจ์ ๊ฐ์ฒด๊ฐ ์๋๋ฏ๋ก ํจ์๋ก์ ๊ธฐ๋ฅํ๋ ๊ฐ์ฒด, ์ฆ ํจ์ ๊ฐ์ฒด๋ ๋ฐ๋์ callable์ด์ด์ผ ํ๋ค.
โ ๋ชจ๋ ํจ์ ๊ฐ์ฒด๋ ๋ด๋ถ ๋ฉ์๋ [[Call]]์ ๊ฐ๊ณ ์์ผ๋ฏ๋ก ํธ์ถํ ์ ์๋ค.
ํ์ง๋ง ๋ชจ๋ ํจ์ ๊ฐ์ฒด๊ฐ [[Construct]]๋ฅผ ๊ฐ๋ ๊ฒ์ ์๋๋ค.
โ ํจ์ ๊ฐ์ฒด๋ constructor์ผ ์๋ ์๊ณ non-constructor์ผ ์๋ ์๋ค.
โ ์ฆ, ๋ชจ๋ ํจ์ ๊ฐ์ฒด๋ ํธ์ถํ ์ ์์ง๋ง ๋ชจ๋ ํจ์ ๊ฐ์ฒด๋ฅผ ์์ฑ์ ํจ์๋ก์ ํธ์ถํ ์ ์๋ ๊ฒ์ ์๋๋ค.
(p.243 ๊ทธ๋ฆผ ์ฐธ๊ณ ํ๋ฉด ์ดํดํ๊ธฐ ์ฌ์)
2-5. constructor์ non-contructor์ ๊ตฌ๋ถ
์๋ฐ์คํฌ๋ฆฝํธ ์์ง์ ํจ์ ์ ์๋ฅผ ํ๊ฐํ์ฌ ํจ์ ๊ฐ์ฒด๋ฅผ ์์ฑํ ๋ ํจ์ ์ ์ ๋ฐฉ์์ ๋ฐ๋ผ ํจ์๋ฅผ constructor์ non-constructor๋ก ๊ตฌ๋ถํ๋ค.
๐๐ป constructor: ํจ์ ์ ์ธ๋ฌธ, ํจ์ ํํ์, ํด๋์ค
๐๐ปย non-constructor: ๋ฉ์๋(ES6), ํ์ดํ ํจ์
์ด ๋ ์ฃผ์ํ ๊ฒ์ ECMAScript ์ฌ์์์ ๋ฉ์๋๋ก ์ธ์ ํ๋ ๋ฒ์๊ฐ ์ผ๋ฐ์ ์ธ ์๋ฏธ์ ๋ฉ์๋๋ณด๋ค ์ข๋ค๋ ๊ฒ์ด๋ค.
// ์ผ๋ฐ ํจ์ ์ ์: ํจ์ ์ ์ธ๋ฌธ, ํจ์ ํํ์
function foo() {}
const bar = function () {};
// ํ๋กํผํฐ x์ ๊ฐ์ผ๋ก ํ ๋น๋ ๊ฒ์ ์ผ๋ฐ ํจ์๋ก ์ ์๋ ํจ์. (๋ฉ์๋๋ก ์ธ์ 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
ํจ์๋ฅผ ํ๋กํผํฐ ๊ฐ์ผ๋ก ์ฌ์ฉํ๋ฉด ์ผ๋ฐ์ ์ผ๋ก ๋ฉ์๋๋ก ํต์นญํ์ง๋ง, ECMAScript ์ฌ์์์ ๋ฉ์๋๋ ES6์ ๋ฉ์๋ ์ถ์ฝ ํํ๋ง์ ์๋ฏธํ๋ค.
โ ํจ์๊ฐ ์ด๋์ ํ ๋น๋์ด ์๋์ง์ ๋ฐ๋ผ ๋ฉ์๋์ธ์ง๋ฅผ ํ๋จํ ๊ฒ์ด ์๋๋ผ, ํจ์ ์ ์ ๋ฐฉ์์ ๋ฐ๋ผ constructor์ non-contructor๋ฅผ ๊ตฌ๋ถํ๋ค.
ํจ์๋ฅผ ์ผ๋ฐ ํจ์๋ก์ ํธ์ถํ๋ฉด ํจ์ ๊ฐ์ฒด์ ๋ด๋ถ ๋ฉ์๋ [[Call]]์ด ํธ์ถ๋๊ณ new ์ฐ์ฐ์์ ํจ๊ป ์์ฑ์ ํจ์๋ก์ ํธ์ถํ๋ฉด ๋ด๋ถ ๋ฉ์๋ [[Construct]]๊ฐ ํธ์ถ๋๋ค. non-constructor์ธ ํจ์ ๊ฐ์ฒด๋ ๋ด๋ถ ๋ฉ์๋ [[Construct]]๋ฅผ ๊ฐ์ง ์๋๋ค.
โ non-constructor์ธ ํจ์ ๊ฐ์ฒด๋ฅผ ์์ฑ์ ํจ์๋ก์ ํธ์ถํ๋ฉด ์๋ฌ๊ฐ ๋ฐ์ํ๋ค.
2-6. new ์ฐ์ฐ์
์ผ๋ฐ ํจ์์ ์์ฑ์ ํจ์์ ํน๋ณํ ํ์์ ์ฐจ์ด๋ ์๋ค.
new ์ฐ์ฐ์์ ํจ๊ป ํจ์๋ฅผ ํธ์ถํ๋ฉด ํด๋น ํจ์๋ ์์ฑ์ ํจ์๋ก ๋์ํ๋ค.
โ ํจ์ ๊ฐ์ฒด์ ๋ด๋ถ ๋ฉ์๋ [[Call]]์ด ํธ์ถ๋๋ ๊ฒ์ด ์๋๋ผ [[Contruct]]๊ฐ ํธ์ถ๋๋ค. (๋จ, new ์ฐ์ฐ์์ ํจ๊ป ํธ์ถํ๋ ํจ์๋ non-constructor๊ฐ ์๋ constructor์ด์ด์ผ ํ๋ค.)
// ์์ฑ์ ํจ์๋ก์ ์ ์ํ์ง ์์ ์ผ๋ฐ ํจ์
function add(x, y) {
return x + y;
}
// ์์ฑ์ ํจ์๋ก์ ์ ์ํ์ง ์์ ์ผ๋ฐ ํจ์๋ฅผ new ์ฐ์ฐ์์ ํจ๊ป ํธ์ถ
let inst = new add();
// ํจ์๊ฐ ๊ฐ์ฒด๋ฅผ ๋ฐํํ์ง ์์ผ๋ฏ๋ก ๋ฐํ๋ฌธ์ด ๋ฌด์๋๋ค. ๋ฐ๋ผ์ ๋น ๊ฐ์ฒด๊ฐ ์์ฑ๋์ด ๋ฐํ๋๋ค.
console.log(isnt); // {}
// ๊ฐ์ฒด๋ฅผ ๋ฐํํ๋ ์ผ๋ฐ ํจ์
function createUser(name, role) {
return { name, role };
}
// ์ผ๋ฐ ํจ์๋ฅผ new ์ฐ์ฐ์์ ํจ๊ป ํธ์ถ
inst = new createUser('Lee', 'admin');
// ํจ์๊ฐ ์์ฑํ ๊ฐ์ฒด๋ฅผ ๋ฐํํ๋ค.
console.log(inst); // {name: 'Lee', role: 'admin'}
๋ฐ๋๋ก new ์ฐ์ฐ์ ์์ด ์์ฑ์ ํจ์๋ฅผ ํธ์ถํ๋ฉด ์ผ๋ฐ ํจ์๋ก ํธ์ถ๋๋ค.
โ ํจ์ ๊ฐ์ฒด์ ๋ด๋ถ ๋ฉ์๋ [[Construct]]๊ฐ ํธ์ถ๋๋ ๊ฒ์ด ์๋๋ผ [[Call]]์ด ํธ์ถ๋๋ค.
function Circle(radius) {
this.radius = radius;
this.getDiameter = function () {
return 2 * this.radius;
};
}
// new ์ฐ์ฐ์ ์์ด ์์ฑ์ ํจ์ ํธ์ถํ๋ฉด ์ผ๋ฐ ํจ์๋ก์ ํธ์ถ๋๋ค.
const circle = Circle(5);
console.log(circle); // undefined
// ์ผ๋ฐ ํจ์ ๋ด๋ถ์ this๋ ์ ์ญ ๊ฐ์ฒด window๋ฅผ ๊ฐ๋ฆฌํจ๋ค.
console.log(radius); // 5
console.log(getDiameter()); // 10
circle.getDiameter(); // TypeError: Cannot read property 'getDiameter' of undefined
Circle ํจ์๋ฅผ new ์ฐ์ฐ์์ ํจ๊ป ์์ฑ์ ํจ์๋ก์ ํธ์ถํ๋ฉด ํจ์ ๋ด๋ถ์ this๋ Circle ์์ฑ์ ํจ์๊ฐ ์์ฑํ ์ธ์คํด์ค๋ฅผ ๊ฐ๋ฆฌํจ๋ค.
์ ์์ ์ Circle ํจ์๋ ์ผ๋ฐ ํจ์๋ก์ ํธ์ถ๋์๊ธฐ ๋๋ฌธ์ Circle ํจ์ ๋ด๋ถ์ this๋ ์ ์ญ ๊ฐ์ฒด window๋ฅผ ๊ฐ๋ฆฌํจ๋ค.
โ radius ํ๋กํผํฐ์ getDiameter ๋ฉ์๋๋ ์ ์ญ ๊ฐ์ฒด์ ํ๋กํผํฐ์ ๋ฉ์๋๊ฐ ๋๋ค.
2-7. new.target
์์ฑ์ ํจ์๊ฐ new ์ฐ์ฐ์ ์์ด ํธ์ถ๋๋ ๊ฒ์ ๋ฐฉ์งํ๊ธฐ ์ํด ํ์ค์นผ ์ผ์ด์ค ์ปจ๋ฒค์ ์ ์ฌ์ฉํ๋ค ํ๋๋ผ๋ ์ค์๋ ์ธ์ ๋ ๋ฐ์ํ ์ ์๋ค.
์ด๋ฌํ ์ํ์ฑ์ ํํผํ๊ธฐ ์ํด ES6์์๋ new.target์ ์ง์ํ๋ค.
new.target์ this์ ์ ์ฌํ๊ฒ constructor์ธ ๋ชจ๋ ํจ์ ๋ด๋ถ์์ ์๋ฌต์ ์ธ ์ง์ญ ๋ณ์์ ๊ฐ์ด ์ฌ์ฉ๋๋ฉฐ ๋ฉํ ํ๋กํผํฐ๋ผ๊ณ ๋ถ๋ฅธ๋ค.
ํจ์ ๋ด๋ถ์์ new.target์ ์ฌ์ฉํ๋ฉด new ์ฐ์ฐ์์ ํจ๊ป ์์ฑ์ ํจ์๋ก์ ํธ์ถ๋์๋์ง ํ์ธํ ์ ์๋ค. new ์ฐ์ฐ์์ ํจ๊ป ์์ฑ์ ํจ์๋ก์ ํธ์ถ๋๋ฉด ํจ์ ๋ด๋ถ์ new.target์ ํจ์ ์์ ์ ๊ฐ๋ฆฌํจ๋ค. new ์ฐ์ฐ์ ์์ด ์ผ๋ฐ ํจ์๋ก์ ํธ์ถ๋ ํจ์ ๋ด๋ถ์ new.target์ undefined๋ค.
โ ํจ์ ๋ด๋ถ์์ new.target์ ์ฌ์ฉํ์ฌ new ์ฐ์ฐ์์ ์์ฑ์ ํจ์๋ก์ ํธ์ถํ๋์ง ํ์ธํ์ฌ ๊ทธ๋ ์ง ์์ ๊ฒฝ์ฐ new ์ฐ์ฐ์์ ํจ๊ป ์ฌ๊ท ํธ์ถ์ ํตํด ์์ฑ์ ํจ์๋ก์ ํธ์ถํ ์ ์๋ค.
// ์์ฑ์ ํจ์
function Circle(radius) {
// ์ด ํจ์๊ฐ new ์ฐ์ฐ์์ ํจ๊ป ํธ์ถ๋์ง ์์๋ค๋ฉด new.target์ undefined๋ค.
if (!new.target) {
// 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()); // 10
// 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
new ์ฐ์ฐ์์ ํจ๊ป ์์ฑ์ ํจ์์ ์ํด ์์ฑ๋ ๊ฐ์ฒด(์ธ์คํด์ค)๋ ํ๋กํ ํ์ ์ ์ํด ์์ฑ์ ํจ์์ ์ฐ๊ฒฐ๋๋ค. ์ด๋ฅผ ์ด์ฉํด new ์ฐ์ฐ์์ ํจ๊ป ํธ์ถ๋์๋์ง ํ์ธํ ์ ์๋ค.
(ํ๋กํ ํ์ ๊ณผ instanceof ์ฐ์ฐ์์ ๋ํด์๋ 19์ฅ ํ๋กํ ํ์ ์ ์์ธํ ๋์จ๋ค.)
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); // f anonymous(x) { return x ** x }
f = Function('x', 'return x ** x');
console.log(f); // f anonymous(x) { return x ** x
ํ์ง๋ง String, Number, Boolean ์์ฑ์ ํจ์๋ new ์ฐ์ฐ์์ ํจ๊ป ํธ์ถํ์ ๋ String, Number, Boolean ๊ฐ์ฒด๋ฅผ ์์ฑํ์ฌ ๋ฐํํ์ง๋ง 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