์๋ฐ์คํฌ๋ฆฝํธ๋ ๋ช ๋ นํ, ํจ์ํ, ํ๋กํ ํ์ ๊ธฐ๋ฐ ๊ฐ์ฒด์งํฅ ํ๋ก๊ทธ๋๋ฐ์ ์ง์ํ๋ ๋ฉํฐ ํจ๋ฌ๋ค์ ํ๋ก๊ทธ๋๋ฐ ์ธ์ด์ด๋ค.
์๋ฐ์คํฌ๋ฆฝํธ๋ ๊ฐ์ฒด ๊ธฐ๋ฐ์ ํ๋ก๊ทธ๋๋ฐ ์ธ์ด์ด๋ฉฐ ์๋ฐ์คํฌ๋ฆฝํธ๋ฅผ ์ด๋ฃจ๊ณ ์๋ ๊ฑฐ์ "๋ชจ๋ ๊ฒ"์ด ๊ฐ์ฒด๋ค.
๊ฐ์ฒด์งํฅ ํ๋ก๊ทธ๋๋ฐ์ ์ฌ๋ฌ ๊ฐ์ ๋ ๋ฆฝ์ ๋จ์, ์ฆ ๊ฐ์ฒด์ ์งํจ์ผ๋ก ํ๋ก๊ทธ๋จ์ ํํํ๋ ค๋ ํ๋ก๊ทธ๋๋ฐ ํจ๋ฌ๋ค์์ ๋งํ๋ค.
๊ฐ์ฒด์งํฅ ํ๋ก๊ทธ๋๋ฐ์ ์ค์ธ๊ณ์ ์ค์ฒด๋ฅผ ์ธ์ํ๋ ์ฒ ํ์ ์ฌ๊ณ ๋ฅผ ํ๋ก๊ทธ๋๋ฐ์ ์ ๋ชฉํ๋ ค๋ ์๋์์ ์์ํ๋ค. ์ค์ฒด๋ ํน์ง์ด๋ ์ฑ์ง์ ๋ํ๋ด๋ ์์ฑ์ ๊ฐ์ง๊ณ ์๊ณ , ์ด๋ฅผ ํตํด ์ค์ฒด๋ฅผ ์ธ์ํ๊ฑฐ๋ ๊ตฌ๋ณํ ์ ์๋ค.
๋ค์ํ ์์ฑ ์ค์์ ํ๋ก๊ทธ๋๋ฐ์ ํ์ํ ์์ฑ๋ง ๊ฐ์ถ๋ ค ๋ด์ด ํํํ๋ ๊ฒ์ ์ถ์ํ๋ผ ํ๋ค.
์์์ ๊ฐ์ฒด์งํฅ ํ๋ก๊ทธ๋๋ฐ์ ํต์ฌ ๊ฐ๋
์ผ๋ก, ์ด๋ค ๊ฐ์ฒด์ ํ๋กํผํฐ ๋๋ ๋ฉ์๋๋ฅผ ๋ค๋ฅธ ๊ฐ์ฒด๊ฐ ์์๋ฐ์ ๊ทธ๋๋ก ์ฌ์ฉํ ์ ์๋ ๊ฒ์ ๋งํ๋ค.
์๋ฐ์คํฌ๋ฆฝํธ๋ ํ๋กํ ํ์
์ ๊ธฐ๋ฐ์ผ๋ก ์์์ ๊ตฌํํ์ฌ ๋ถํ์ํ ์ค๋ณต์ ์ ๊ฑฐํ๋ค. ์ค๋ณต์ ์ ๊ฑฐํ๋ ๋ฐฉ๋ฒ์ ๊ธฐ์กด์ ์ฝ๋๋ฅผ ์ ๊ทน์ ์ผ๋ก ์ฌ์ฌ์ฉํ๋ ๊ฒ์ด๋ค.
// ์์ฑ์ ํจ์
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.1415926
console.log(circle2.getArea()); // 12.56637
์์์ ํตํด ๋ถํ์ํ ์ค๋ณต์ ์ ๊ฑฐํด ๋ณด์. ์๋ฐ์คํฌ๋ฆฝํธ๋ ํ๋กํ ํ์ ์ ๊ธฐ๋ฐ์ผ๋ก ์์์ ๊ตฌํํ๋ค.
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.14159265
console.log(circle2.getArea()); // 12.5663
ํ๋กํ ํ์
๊ฐ์ฒด๋ ๊ฐ์ฒด์งํฅ ํ๋ก๊ทธ๋๋ฐ์ ๊ทผ๊ฐ์ ์ด๋ฃจ๋ ๊ฐ์ฒด ๊ฐ ์์์ ๊ตฌํํ๊ธฐ ์ํด ์ฌ์ฉ๋๋ค.
ํ๋กํ ํ์
์ ์ด๋ค ๊ฐ์ฒด์ ์์ ๊ฐ์ฒด์ ์ญํ ์ ํ๋ ๊ฐ์ฒด๋ก์ ๋ค๋ฅธ ๊ฐ์ฒด์ ๊ณต์ ํ๋กํผํฐ๋ฅผ ์ ๊ณตํ๋ค. ํ๋กํ ํ์
์ ์์๋ฐ์ ํ์ ๊ฐ์ฒด๋ ์์ ๊ฐ์ฒด์ ํ๋กํผํฐ๋ฅผ ์์ ์ ํ๋กํผํฐ์ฒ๋ผ ์์ ๋กญ๊ฒ ์ฌ์ฉํ ์ ์๋ค.
๋ชจ๋ ๊ฐ์ฒด๋ [[Prototype]] ์ด๋ผ๋ ๋ด๋ถ ์ฌ๋กฏ์ ๊ฐ์ง๋ฉฐ, ์ด ๋ด๋ถ ์ฌ๋กฏ์ ๊ฐ์ ํ๋กํ ํ์
์ ์ฐธ์กฐ๋ค. [[Prototype]]์ ์ ์ฅ๋๋ ํ๋กํ ํ์
์ ๊ฐ์ฒด ์์ฑ ๋ฐฉ์์ ์ํด ๊ฒฐ์ ๋๋ค. ์ฆ, ๊ฐ์ฒด๊ฐ ์์ฑ๋ ๋ ๊ฐ์ฒด ์์ฑ ๋ฐฉ์์ ๋ฐ๋ผ ํ๋กํ ํ์
์ด ๊ฒฐ์ ๋๊ณ [[Prototype]]์ ์ ์ฅ๋๋ค.
๋ชจ๋ ๊ฐ์ฒด๋ ํ๋์ ํ๋กํ ํ์
์ ๊ฐ๋๋ค. ๊ทธ๋ฆฌ๊ณ ๋ชจ๋ ํ๋กํ ํ์
์ ์์ฑ์ ํจ์์ ์ฐ๊ฒฐ๋์ด ์๋ค. ์ฆ, ๊ฐ์ฒด์ ํ๋กํ ํ์
๊ณผ ์์ฑ์ ํจ์๋ ์๋ก ์ฐ๊ฒฐ๋์ด ์๋ค.
๋ชจ๋ ๊ฐ์ฒด๋ __proto__ ์ ๊ทผ์ ํ๋กํผํฐ๋ฅผ ํตํด ์์ ์ ํ๋กํ ํ์ , ์ฆ [[Prototype]] ๋ด๋ถ ์ฌ๋กฏ์ ๊ฐ์ ์ ์ผ๋ก ์ ๊ทผํ ์ ์๋ค.
const person = {name: 'Lee'};
์๋ฐ์คํฌ๋ฆฝํธ๋ ์์น์ ์ผ๋ก ๋ด๋ถ ์ฌ๋กฏ๊ณผ ๋ด๋ถ ๋ฉ์๋์ ์ง์ ์ ์ผ๋ก ์ ๊ทผํ๊ฑฐ๋ ํธ์ถํ ์ ์๋ ๋ฐฉ๋ฒ์ ์ ๊ณตX ๋จ, ์ผ๋ถ ๋ด๋ถ ์ฌ๋กฏ๊ณผ ๋ด๋ถ ๋ฉ์๋์ ํํ์ฌ ๊ฐ์ ์ ์ผ๋ก ์ ๊ทผํ ์ ์๋ ์๋จ์ ์ ๊ณตํ๊ธฐ๋ ํ๋ค.
__proto__ ์ ๊ทผ์ ํ๋กํผํฐ๋ ๊ฐ์ฒด๊ฐ ์ง์ ์์ ํ๋ ํ๋กํผํฐ๊ฐ ์๋๋ผ Object.prototype์ ํ๋กํผํฐ๋ค. ๋ชจ๋ ๊ฐ์ฒด๋ ์์์ ํตํด Object.prototype.__proto__ ์ ๊ทผ์ ํ๋กํผํฐ๋ฅผ ์ฌ์ฉํ ์ ์๋ค.
[[Prototype]] ๋ด๋ถ ์ฌ๋กฏ์ ๊ฐ, ์ฆ ํ๋กํ ํ์ ์ ์ ๊ทผํ๊ธฐ ์ํด ์ ๊ทผ์ ํ๋กํผํฐ๋ฅผ ์ฌ์ฉํ๋ ์ด์ ๋ ์ํธ ์ฐธ์กฐ์ ์ํด ํ๋กํ ํ์ ์ฒด์ธ์ด ์์ฑ๋๋ ๊ฒ์ผ๋ฅด ๋ฐฉ์งํ๊ธฐ ์ํด์๋ค.
const parent = {};
const child = {};
// child์ ํ๋กํ ํ์
์ parent๋ก ์ค์
child.__proto__ = parent;
// parent์ ํ๋กํ ํ์
์ child๋ก ์ค์
parent.__proto__ = child; // TypeError: Cyclic __proto__ value
ํ๋กํ ํ์
์ฒด์ธ์ ๋จ๋ฐฉํฅ ๋งํฌ๋ ๋ฆฌ์คํธ๋ก ๊ตฌํ๋์ด์ผ ํ๋ค. ์ฆ, ํ๋กํผํฐ ๊ฒ์ ๋ฐฉํฅ์ด ํ์ชฝ ๋ฐฉํฅ์ผ๋ก๋ง ํ๋ฌ๊ฐ์ผ ํ๋ค.
ํ์ง๋ง ์์ ์ฝ๋์ฒ๋ผ ์๋ก๊ฐ ์์ ์ ํ๋กํ ํ์
์ด ๋๋ ๋น์ ์์ ์ธ ํ๋กํ ํ์
์ฒด์ธ, ๋ค์ ๋งํด ์ํ ์ฐธ์กฐํ๋ ํ๋กํ ํ์
์ฒด์ธ์ด ๋ง๋ค์ด์ง๋ฉด ๋ฌดํ ๋ฃจํ์ ๋น ์ ธ ์๋ฌ๋ฅผ ๋ฐ์์ํจ๋ค.
๋ชจ๋ ๊ฐ์ฒด๊ฐ __proto__ ์ ๊ทผ์ ํ๋กํผํฐ๋ฅผ ์ฌ์ฉํ ์ ์๋ ๊ฒ์ ์๋๊ธฐ ๋๋ฌธ์ __proto__ ์ ๊ทผ์ ํ๋กํผํฐ๋ฅผ ํตํด ํ๋กํ ํ์ ์ ์ ๊ทผํ๋ ๊ฒ์ ๊ถ์ฅํ์ง ์๋๋ค.
๋ฐ๋ผ์ ํ๋กํผํฐ ๋์ ํ๋กํ ํ์ ์ ์ฐธ์กฐ๋ฅผ ์ทจ๋ํ๊ณ ์ถ์ ๊ฒฝ์ฐ์๋ Object.getPrototpyeOf ๋ฉ์๋๋ 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
ํจ์ ๊ฐ์ฒด๋ง์ด ์์ ํ๋ prototype ํ๋กํผํฐ๋ ์์ฑ์ ํจ์๊ฐ ์์ฑํ ์ธ์คํด์ค์ ํ๋กํ ํ์ ์ ๊ฐ๋ฆฌํจ๋ค.
// ํจ์ ๊ฐ์ฒด๋ prototype ํ๋กํผํฐ๋ฅผ ์์ ํ๋ค.
(function () {}).hasOwnProperty('prototype'); // true
// ์ผ๋ฐ ๊ฐ์ฒด๋ prototype ํ๋กํผํฐ๋ฅผ ์์ ํ์ง ์๋๋ค.
({}).hasOwnProperty('prototype'); // false
prototype ํ๋กํผํฐ๋ ์์ฑ์ ํจ์๊ฐ ์์ฑํ ๊ฐ์ฒด์ ํ๋กํ ํ์ ์ ๊ฐ๋ฆฌํจ๋ค. ๋ฐ๋ผ์ ์์ฑ์ ํจ์๋ก ํธ์ถํ ์ ์๋ ํจ์, ์ฆ non-constructor์ธ ํ์ดํ ํจ์์ ES6 ๋ฉ์๋ ์ถ์ฝ ํํ์ผ๋ก ์ ์ํ ๋ฉ์๋๋ prototype ํ๋กํผํฐ๋ฅผ ์์ ํ์ง ์์ผ๋ฉฐ ํ๋กํ ํ์ ๋ ์์ฑํ์ง ์๋๋ค.
๋ชจ๋ ๊ฐ์ฒด๊ฐ ๊ฐ์ง๊ณ ์๋(์๋ฐํ ๋งํ๋ฉด Object.prototype์ผ๋ก๋ถํฐ ์์๋ฐ์) __proto__ ์ ๊ทผ์ ํ๋กํผํฐ์ ํจ์ ๊ฐ์ฒด๋ง์ด ๊ฐ์ง๊ณ ์๋ prototype ํ๋กํผํฐ๋ ๊ฒฐ๊ตญ ๋์ผํ ํ๋กํ ํ์ ์ ๊ฐ๋ฆฌํจ๋ค.
๊ตฌ๋ถ | ์์ | ๊ฐ | ์ฌ์ฉ ์ฃผ์ฒด | ์ฌ์ฉ ๋ชฉ์ |
---|---|---|---|---|
__proto__ | ๋ชจ๋ ๊ฐ์ฒด | ํ๋กํ ํ์ ์ ์ฐธ์กฐ | ๋ชจ๋ ๊ฐ์ฒด | ๊ฐ์ฒด๊ฐ ์์ ์ ํ๋กํ ํ์ ์ ์ ๊ทธ ๋๋ ๊ต์ฒดํ๊ธฐ ์ํด ์ฌ์ฉ |
prototype ํ๋กํผํฐ | constructor | ํ๋กํ ํ์ ์ ์ฐธ์กฐ | ์์ฑ์ ํจ์ | ์์ฑ์ ํจ์๊ฐ ์์ ์ด ์์ฑํ ๊ฐ์ฒด(์ธ์คํด์ค)์ ํ๋กํ ํ์ ์ ํ ๋นํ๊ธฐ ์ํด ์ฌ์ฉ |
๋ชจ๋ ํ๋กํ ํ์ ์ constructor ํ๋กํผํฐ๋ฅผ ๊ฐ๋๋ค. ์ด constructor ํ๋กํผํดใด prototype ํ๋กํผํฐ๋ก ์์ ์ ์ฐธ์กฐํ๊ณ ์๋ ์์ฑ์ ํจ์๋ฅผ ๊ฐ๋ฆฌํจ๋ค. ์ด ์ฐ๊ฒฐ์ ์์ฑ์ ํจ์๊ฐ ์์ค๋ ๋, ์ฆ ํจ์ ๊ฐ์ฒด๊ฐ ์์ฑ๋ ๋ ์ด๋ค์ง๋ค.
// ์์ฑ์ ํจ์
function Person(name) {
this.name = name;
}
const me = new Person('Lee');
// me ๊ฐ์ฒด์ ์์ฑ์ ํจ์๋ Person์ด๋ค.
console.log(me.constructor === Person); // true
์์ฑ์ ํจ์์ ์ํด ์์ฑ๋ ์ธ์คํด์ค๋ ํ๋กํ ํ์ ์ constructor ํ๋กํผํฐ์ ์ํด ์์ฑ์ ํจ์์ ์ฐ๊ฒฐ๋๋ค.
// obj ๊ฐ์ฒด๋ฅผ ์์ฑํ ํจ์๋ Object์ด๋ค.
const obj = new Object();
console.log(obj.constructor === Object); // true
// add ํจ์ ๊ฐ์ฒด๋ฅผ ์์ฑํ ์์ฑ์ ํจ์๋ Function์ด๋ค.
const add = new Function('a','b','return a + b');
console.log(add.constructor === Function); //true
// ์์ฑ์ ํจ์
function Person(name) {
this.name = name;
}
// me ๊ฐ์ฒด๋ฅผ ์์ฑํ ์์ฑ์ ํจ์๋ Person์ด๋ค.
const me = new Person('Lee');
console.log(me.constructor === Person); // true
๋ฆฌํฐ๋ด ํ๊ธฐ๋ฒ์ ์ํ ๊ฐ์ฒด ์์ฑ ๋ฐฉ์๊ณผ ๊ฐ์ด ๋ช ์์ ์ผ๋ก new ์ฐ์ฐ์์ ํจ๊ป ์์ฑ์ ํจ์๋ฅผ ํธ์ถํ์ฌ ์ธ์คํด์ค๋ฅผ ์์ฑํ์ง ์๋ ๊ฐ์ฒด ์์ฑ ๋ฐฉ์๋ ์๋ค.
// ๊ฐ์ฒด ๋ฆฌํฐ๋ด
const obj = {};
// ํจ์ ๋ฆฌํฐ๋ด
const add = function (a,b) { return a+b;;
// ๋ฐฐ์ด ๋ฆฌํฐ๋ด
const arr = [1,2,3];
// ์ ๊ท ํํ์ ๋ฆฌํฐ๋ด
const regexp = /is/ig;
๋ฆฌํฐ๋ด ํ๊ธฐ๋ฒ์ ์ํด ์์ฑ๋ ๊ฐ์ฒด๋ ๋ฌผ๋ก ํ๋กํ ํ์ ์ด ์กด์ฌํ๋ค. ํ์ง๋ง ๋ฆฌํฐ๋ด ํ๊ธฐ๋ฒ์ ์ํด ์์ฑ๋ ๊ฐ์ฒด์ ๊ฒฝ์ฐ ํ๋กํ ํ์ ์ constructor ํ๋กํผํฐ๊ฐ ๊ฐ๋ฆฌํค๋ ์์ฑ์ ํจ์๊ฐ ๋ฐ๋์ ๊ฐ์ฒด๋ฅผ ์์ฑํ ์์ฑ์ ํจ์๋ผ๊ณ ๋จ์ ํ ์๋ ์๋ค.
ํ๋กํ ํ์ ๊ณผ ์์ฑ์ ํจ์๋ ๋จ๋ ์ผ๋ก ์กด์ฌํ ์ ์๊ณ ์ธ์ ๋ ์์ผ๋ก ์กด์ฌํ๋ค.
ํ๋กํ ํ์
์ ์์ฑ์ ํจ์๊ฐ ์์ฑ๋๋ ์์ ์ ๋๋ถ์ด ์์ฑ๋๋ค/
ํ๋กํ ํ์
๊ณผ ์์ฑ์ ํจ์๋ ๋จ๋
์ผ๋ก ์กด์ฌํ ์ ์๊ณ ์ธ์ ๋ ์์ผ๋ก ์กด์ฌํ๊ธฐ ๋๋ฌธ์ด๋ค.
์์ฑ์ ํจ์๋ก์ ํธ์ถํ ์ ์๋ ํจ์, ์ฆ constructor๋ ํจ์ ์ ์๊ฐ ํ๊ฐ๋์ด ํจ์ ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ ์์ ์ ํ๋กํ ํ์ ๋ ๋๋ถ์ด ์์ฑ๋๋ค.
// ํจ์ ์ ์(constructor)๊ฐ ํ๊ฐ๋์ด ํจ์ ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ ์์ ์ ํ๋กํ ํ์
๋ ๋๋ถ์ด ์์ฑ๋๋ค.
console.log(Person.prototype); // {constructor: f}
// ์์ฑ์ ํจ์
function Person(name) {
this.name = name;
}
// ์์ฑ์ ํจ์๋ก์ ํธ์ถํ ์ ์๋ ํจ์, ์ฆ non-constructor๋ ํ๋กํ ํ์
์ด ์์ฑ๋์ง ์๋๋ค.
// ํ์ดํ ํจ์๋ non-constructor๋ค.
const Person = name => {
this.name = name;
};
// non-constructor๋ ํ๋กํ ํ์
์ด ์์ฑ๋์ง ์๋๋ค.
console.log(Person.prototype); // undefined
์์ฑ๋ ํ๋กํ ํ์
์ ์ค์ง constructor ํ๋กํผํฐ๋ง์ ๊ฐ๋ ๊ฐ์ฒด๋ค.
ํ๋กํ ํ์
๋ ๊ฐ์ฒด์ด๊ณ ๋ชจ๋ ๊ฐ์ฒด๋ ํ๋กํ ํ์
์ ๊ฐ์ง๋ฏ๋ก ํ๋กํ ํ์
๋ ์์ ์ ํ๋กํ ํ์
์ ๊ฐ๋๋ค.
์์ฑ๋ ํ๋กํ ํ์
์ ํ๋กํ ํ์
์ Object.prototype์ด๋ค.
Object, String, Number, Function, Array, RegExp, Date, Promise ๋ฑ๊ณผ ๊ฐ์ ๋นํธ์ธ ์์ฑ์ ํจ์๋ ์ผ๋ฐ ํจ์์ ๋ง์ฐฌ๊ฐ์ง๋ก ๋นํธ์ธ ์์ฑ์ ํจ์๊ฐ ์์ฑ๋๋ ์์ ์ ํ๋กํ ํ์ ์ด ์์ฑ๋๋ค.
๊ฐ์ฒด๊ฐ ์์ฑ๋๊ธฐ ์ด์ ์ ์์ฑ์ ํจ์์ ํ๋กํ ํ์ ์ ์ด๋ฏธ ๊ฐ์ฒดํ ๋์ด ์กด์ฌํ๋ค.์ดํ ์์ฑ์ ํจ์ ๋๋ ๋ฆฌํฐ๋ด ํ๊ธฐ๋ฒ์ผ๋ก ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ฉด ํ๋กํ ํ์ ์ ์์ฑ๋ ๊ฐ์ฒด์ [[Prototype]] ๋ด๋ถ ์ฌ๋กฏ์ ํ ๋น๋๋ค.
๊ฐ์ฒด๋ ๋ค์๊ณผ ๊ฐ์ด ๋ค์ํ ์์ฑ ๋ฐฉ๋ฒ์ด ์๋ค.
- ๊ฐ์ฒด ๋ฆฌํฐ๋ด
- Object ์์ฑ์ ํจ์
- ์์ฑ์ ํจ์
- Object.create ๋ฉ์๋
- ํด๋์ค(ES6)
์๋ฐ์คํฌ๋ฆฝํธ ์์ง์ ๊ฐ์ฒด ๋ฆฌํฐ๋ด์ ํ๊ฐํ์ฌ ๊ฐ์ฒด๋ฅผ ์์ฑํ ๋ ์ถ์ ์ฐ์ฐ OrdinaryObjectCreate๋ฅผ ํธ์ถํ๋ค ์ด๋ ์ถ์ ์ฐ์ฐ OrdinaryObjectCreae์ ์ ๋ฌ๋๋ ํ๋กํ ํ์ ์ Object.prototype์ด๋ค. ์ฆ, ๊ฐ์ฒด ๋ฆฌํฐ๋ด์ ์ํด ์์ฑ๋๋ ๊ฐ์ฒด์ ํ๋กํ ํ์ ์ Object.prototype์ด๋ค.
const obj = { x: 1 };
Object ์์ฑ์ ํจ์๋ฅผ ์ธ์ ์์ด ํธ์ถํ๋ฉด ๋น ๊ฐ์ฒด๊ฐ ์์ฑ๋๋ค. Object ์์ฑ์ ํจ์๋ฅผ ํธ์ถํ๋ฉด ๊ฐ์ฒด ๋ฆฌํฐ๋ด๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก ์ถ์ ์ฐ์ฐ OrdinaryObjectCreate๊ฐ ํธ์ถ๋๋ค. ์ด๋ ์ถ์ ์ฐ์ฐ OrdinaryObjectCreae์ ์ ๋ฌ๋๋ ํ๋กํ ํ์ ์ Object.prototype์ด๋ค. ์ฆ Object ์์ฑ์ ํจ์์ ์ํด ์์ฑ๋๋ ๊ฐ์ฒด์ ํ๋กํ ํ์ ์ Object.prototype์ด๋ค.
const obj = new Object();
obj.x = 1;
Object ์์ฑ์ ํจ์์ ์ํด ์์ฑ๋ obj ๊ฐ์ฒด๋ Object.prototype์ ํ๋กํ ํ์
์ ๊ฐ๊ฒ ๋๋ฉฐ, ์ด๋ก์จ Object.prototype์ ์์๋ฐ๋๋ค.
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 ์์ฑ์ ํจ์ ๋ฐฉ์์ ์ผ๋จ ๋น ๊ฐ์ฒด๋ฅผ ์์ฑํ ์ดํ ํ๋กํผํฐ๋ฅผ ์ถ๊ฐํด์ผ ํ๋ค.
new ์ฐ์ฐ์์ ํจ๊ป ์์ฑ์ ํจ์๋ฅผ ์ฌ์ฉํด ์ธ์คํด์ค๋ฅผ ์์ฑํ ๋ ์ถ์ ์ฐ์ฐ OrdinaryObjectCreate๊ฐ ํธ์ถ๋๋ค. ์ด๋ ์ถ์ ์ฐ์ฐ OrdinaryObjectCreate์ ์ ๋ฌ๋๋ ํ๋กํ ํ์ ์ ์์ฑ์ ํจ์์ prototype ํ๋กํผํฐ์ ๋ฐ์ธ๋ฉ๋์ด ์๋ ๊ฐ์ฒด๋ค. ์ฆ, ์์ฑ์ ํจ์์ ์ํด ์์ฑ๋๋ ๊ฐ์ฒด์ ํ๋กํ ํ์ ์ ์์ฑ์ ํจ์์ prototype ํ๋กํผํฐ์ ๋ฐ์ธ๋ฉ๋์ด ์๋ ๊ฐ์ฒด๋ค.
function Person(name){
this.name = name;
}
const me = new Person('Lee');
function Person(name) {
this.name = name;
}
// ํ๋กํ ํ์
๋ฉ์๋
Person.prototype.sayHello = function () {
console.log(`Hi! My name is ${this.name}`);
};
const me = new Person('Lee');
// hasOwnProperty๋ Object.prototype์ ๋ฉ์๋๋ค.
console.log(me.hasOwnProperty('name')); // true
Person ์์ฑ์ ํจ์์ ์ํด ์์ฑ๋ me ๊ฐ์ฒด๋ Object.prototype์ ๋ฉ์๋์ธ hasOwnProperty๋ฅผ ํธ์ถํ ์ ์๋ค. ์ด๊ฒ์ me ๊ฐ์ฒด๊ฐ Person.prototype๋ฟ๋ง ์๋๋ผ Object.prtotype๋ ์์๋ฐ์๋ค๋ ๊ฒ์ ์๋ฏธํ๋ค.
์๋ฐ์คํฌ๋ฆฝํธ๋ ๊ฐ์ฒด์ ํ๋กํผํฐ(๋ฉ์๋ ํฌํจ)์ ์ ๊ทผํ๋ ค๊ณ ํ ๋ ํด๋น ๊ฐ์ฒด์ ์ ๊ทผํ๋ ค๋ ํ๋กํผํฐ๊ฐ ์๋ค๋ฉด [[Prototype]] ๋ด๋ถ ์ฌ๋กฏ์ ์ฐธ์กฐ๋ฅผ ๋ฐ๋ผ ์์ ์ ๋ถ๋ชจ ์ญํ ์ ํ๋ ํ๋กํ ํ์ ์ ํ๋กํผํฐ๋ฅผ ์์ฐจ์ ์ผ๋ก ๊ฒ์ํ๋ค. ์ด๋ฅผ ํ๋กํ ํ์ ์ฒด์ธ์ด๋ผ ํ๋ค. ํ๋กํ ํ์ ์ฒด์ธ์ ์๋ฐ์คํฌ๋ฆฝํธ๊ฐ ๊ฐ์ฒด์งํฅ ํ๋ก๊ทธ๋๋ฐ์ ์์์ ๊ตฌํํ๋ ๋ฉ์ปค๋์ฆ์ด๋ค.
ํ๋กํ ํ์ ์ฒด์ธ์ ์ต์์์ ์์นํ๋ ๊ฐ์ฒด๋ ์ธ์ ๋ Object.prototype์ด๋ค. ๋ฐ๋ผ์ ๋ชจ๋ ๊ฐ์ฒด๋ Object.prototype์ ์์๋ฐ๋๋ค. Object.prototype์ ํ๋กํ ํ์ ์ฒด์ธ์ ์ข ์ ์ด๋ผ ํ๋ค.
ํ๋กํ ํ์
์ฒด์ธ์ ์์๊ณผ ํ๋กํผํฐ ๊ฒ์์ ์ํ ๋ฉ์ปค๋์ฆ
์ค์ฝํ ์ฒด์ธ์ ์๋ณ์ ๊ฒ์์ ์ํ ๋ฉ์ปค๋์ฆ
const Person = (function () {
// ์์ฑ์ ํจ์
function Person(name) {
this.name = name;
}
// ํ๋กํ ํ์ ๋ฉ์๋
Person.prototype.sayHello = function () {
console.log(`Hi! My name is ${this.name}`);
};
// ์์ฑ์ ํจ์๋ฅผ ๋ฐํ
return Person;
}());
const me = new Person('Lee');
// ์ธ์คํด์ค ๋ฉ์๋
me.sayHello = function () {
console.log(`Hey : My name is ${this.name}`);
};
// ์ธ์คํด์ค ๋ฉ์๋๊ฐ ํธ์ถ๋๋ค. ํ๋กํ ํ์
๋ฉ์๋๋ ์ธ์คํด์ค ๋ฉ์๋์ ์ํด ๊ฐ๋ ค์ง๋ค.
me.sayHello(); // Hey! My name is Lee
ํ๋กํ ํ์
์ด ์์ ํ ํ๋กํผํฐ๋ฅผ ํ๋กํ ํ์
ํ๋กํผํฐ, ์ธ์คํด์ค๊ฐ ์์ ํ ํ๋กํผํฐ๋ฅผ ์ธ์คํด์ค ํ๋กํผํฐ๋ผ๊ณ ํ๋ค.
ํ๋กํ ํ์
ํ๋กํผํฐ์ ๊ฐ์ ์ด๋ฆ์ ํ๋กํผํฐ๋ฅผ ์ธ์คํด์ค์ ์ถ๊ฐํ๋ฉด ํ๋กํ ํ์
์ฒด์ธ์ ๋ฐ๋ผ ํ๋กํ ํ์
ํ๋กํผํฐ๋ฅผ ๊ฒ์ํ์ฌ ํ๋กํ ํ์
ํ๋กํผํฐ๋ฅผ ๋ฎ์ด์ฐ๋ ๊ฒ์ด ์๋๋ผ ์ธ์คํด์ค ํ๋กํผํฐ๋ก ์ถ๊ฐํ๋ค. ์ด๋ ์ธ์คํด์ค ๋ฉ์๋ sayHello๋ ํ๋กํ ํ์
๋ฉ์๋ sayHello๋ฅผ ์ค๋ฒ๋ผ์ด๋ฉํ๊ณ ํ๋กํ ํ์
๋ฉ์๋ sayHello๋ ๊ฐ๋ ค์ง๋ค. ์ด์ฒ๋ผ ์์ ๊ด๊ณ์ ์ํด ํ๋กํผํฐ๊ฐ ๊ฐ๋ ค์ง๋ ํ์์ ํ๋กํผํฐ ์๋์์ด๋ผ ํ๋ค.
โ๏ธ์ค๋ฒ๋ผ์ด๋ฉ
์์ ํด๋์ค๊ฐ ๊ฐ์ง๊ณ ์๋ ๋ฉ์๋๋ฅผ ํ์ ํด๋์ค๊ฐ ์ฌ์ ์ํ์ฌ ์ฌ์ฉํ๋ ๋ฐฉ์์ด๋ค
โ๏ธ์ค๋ฒ๋ก๋ฉ
ํจ์์ ์ด๋ฆ์ ๋์ผํ์ง๋ง ๋งค๊ฐ๋ณ์์ ํ์ ๋๋ ๊ฐ์๊ฐ ๋ค๋ฅธ ๋ฉ์๋๋ฅผ ๊ตฌํํ๊ณ ๋งค๊ฐ๋ณ์์ ์ํด ๋ฉ์๋๋ฅผ ๊ตฌ๋ณํ์ฌ ํธ์ถํ๋ ๋ฐฉ์์ด๋ค. ์๋ฐ์คํฌ๋ฆฝํธ๋ ์ค๋ฒ๋ก๋ฉ์ ์ง์ํ์ง ์์ง๋ง arguments ๊ฐ์ฒด๋ฅผ ์ฌ์ฉํ์ฌ ๊ตฌํํ ์๋ ์๋ค.
ํ์ ๊ฐ์ฒด๋ฅผ ํตํด ํ๋กํ ํ์ ์ get ์ก์ธ์ค๋ ํ์ฉ๋๋ set ์ก์ธ๋๋ ํ์ฉ๋์ง ์๋๋ค.
ํ๋กํ ํ์ ์ ์์์ ๋ค๋ฅธ ๊ฐ์ฒด๋ก ๋ณ๊ฒฝํ ์ ์๋ค. ์ด๊ฒ์ ๋ถ๋ชจ ๊ฐ์ฒด์ธ ํ๋กํ ํ์ ์ ๋์ ์ผ๋ก ๋ณ๊ฒฝํ ์ ์๋ค๋ ๊ฒ์ ์๋ฏธํ๋ค. ์ด๋ฌํ ํน์ง์ ํ์ฉํ์ฌ ๊ฐ์ฒด ๊ฐ์ ์์ ๊ด๊ณ๋ฅผ ๋์ ์ผ๋ก ๋ณ๊ฒฝํ ์ ์๋ค. ํ๋กํ ํ์ ์ ์์ฑ์ ํจ์ ๋๋ ์ธ์คํด์ค์ ์ํด ๊ต์ฒดํ ์ ์๋ค.
const Person = (function () {
function Person(name) {
this.name = name;
}
// โ ์์ฑ์ ํจ์์ prototype ํ๋กํผํฐ๋ฅผ ํตํด ํ๋กํ ํ์
์ ๊ต์ฒด
Person.prototype = {
sayHello() {
console.log(`Hi! My name is ${this.name}`);
}
};
return Person;
}());
const me = new Person('Lee');
โ ์์ Person.prototype์ ๊ฐ์ฒด ๋ฆฌํฐ๋ด์ ํ ๋นํ๋๋ฐ,
์ด๋ Person ์์ฑ์ ํจ์๊ฐ ์์ฑํ ๊ฐ์ฒด์ ํ๋กํ ํ์
์ ๊ฐ์ฒด ๋ฆฌํฐ๋ด๋ก ๊ต์ฒดํ ๊ฒ์ด๋ค.
ํ๋กํ ํ์
์ผ๋ก ๊ต์ฒดํ ๊ฐ์ฒด ๋ฆฌํฐ๋ด์๋ constructor ํ๋กํผํฐ๊ฐ ์๋ค. constructor ํ๋กํผํฐ๋ ์๋ฐ์คํฌ๋ฆฝํธ ์์ง์ด ํ๋กํ ํ์
์ ์์ฑํ ๋ ์๋ฌต์ ์ผ๋ก ์ถ๊ฐํ ํ๋กํผํฐ๋ค. ๋ฐ๋ผ์ me ๊ฐ์ฒด์ ์์ฑ์ ํจ์๋ฅผ ๊ฒ์ํ๋ฉด Person์ด ์๋ Object๊ฐ ๋์จ๋ค.
ํ๋กํ ํ์ ์ ๊ต์ฒดํ๋ฉด constructor ํ๋กํผํฐ์ ์์ฑ์ ํจ์ ๊ฐ์ ์ฐ๊ฒฐ์ด ํ๊ดด๋๋๋ฐ ํ๋กํ ํ์ ์ผ๋ก ๊ต์ฒดํ ๊ฐ์ฒด ๋ฆฌํฐ๋ด์ constructor ํ๋กํผํฐ๋ฅผ ์ถ๊ฐํ์ฌ ํ๋กํ ํ์ ์ constructor ํ๋กํผํฐ๋ฅผ ๋์ด๋ฆฐ๋ค.
ํ๋กํ ํ์
์ ์์ฑ์ ํจ์์ prototype ํ๋กํผํฐ๋ฟ๋ง ์๋๋ผ ์ธ์คํด์ค์ __proto__ ์ ๊ทผ์ ํ๋กํฌํฐ๋ฅผ ํตํด ์ ๊ทผํ ์ ์๋ค. ๋ฐ๋ผ์ ์ธ์คํด์ค์ __proto__ ์ ๊ทผ์ ํ๋กํผํฐ๋ฅผ ํตํด ํ๋กํ ํ์
์ ๊ต์ฒดํ ์ ์๋ค.
์์ฑ์ ํจ์์ prototype ํ๋กํผํฐ์ ๋ค๋ฅธ ์์์ ๊ฐ์ฒด๋ฅผ ๋ฐ์ธ๋ฉํ๋ ๊ฒ์ ๋ฏธ๋์ ์์ฑํ ์ธ์คํด์ค์ ํ๋กํ ํ์
์ ๊ต์ฒดํ๋ ๊ฒ์ด๋ค.
function Person(name) {
this.name = name;
}
const me = new Person("april");
// ํ๋กํ ํ์
์ผ๋ก ๊ต์ฒดํ ๊ฐ์ฒด
const parent = {
// constructor ํ๋กํผํฐ์ ์์ฑ์ ํจ์ ๊ฐ์ ์ฐ๊ฒฐ์ ์ค์
constructor: Person,
sayHello() {
console.log(`Hi! My name is ${this.name}`);
},
};
// ์์ฑ์ ํจ์์ prototype ํ๋กํผํฐ์ ํ๋กํ ํ์
๊ฐ์ ์ฐ๊ฒฐ์ ์ค์
Person.prototype = parent;
// โ me ๊ฐ์ฒด์ ํ๋กํ ํ์
์ parent ๊ฐ์ฒด๋ก ๊ต์ฒดํ๋ค.
Object.setPrototypeOf(me, parent);
// ์ ์ฝ๋๋ ์๋์ ์ฝ๋์ ๋์ผํ๊ฒ ๋์ํ๋ค.
// me.__proto__ = parent;
me.sayHello(); // Hi! My name is april
โ ์์ me ๊ฐ์ฒด์ ํ๋กํ ํ์
์ parent ๊ฐ์ฒด๋ก ๊ต์ฒดํ๋ค.
// constructor ํ๋กํผํฐ๊ฐ ์์ฑ์ ํจ์๋ฅผ ๊ฐ๋ฆฌํจ๋ค.
console.log(me.constructor === Person); // true
console.log(me.constructor === Object); // false
// ์์ฑ์ ํจ์์ prototype ํ๋กํผํฐ๊ฐ ๊ต์ฒด๋ ํ๋กํ ํ์
์ ๊ฐ๋ฆฌํจ๋ค.
console.log(Person.prototype === Object.getPrototypeOf(me)); // true
function Person(name) {
this.name = name;
}
const me = new Person('Lee');
// ํ๋กํ ํ์
์ผ๋ก ๊ต์ฒดํ ๊ฐ์ฒด
const parent = {
// constructor ํ๋กํผํฐ์ ์์ฑ์ ํจ์ ๊ฐ์ ์ฐ๊ฒฐ์ ์ค์
constructor : Person,
sayHello() {
console.log(`Hi! My name is ${this.name}`);
}
};
// ์์ฑ์ ํจ์์ prototype ํ๋กํผํฐ์ ํ๋กํ ํ์
๊ฐ์ ์ฐ๊ฒฐ์ ์ค์
Person.prototype = parent;
// me ๊ฐ์ฒด์ ํ๋กํ ํ์
์ parent ๊ฐ์ฒด๋ก ๊ต์ฒดํ๋ค.
Object.setPrototypeOf(me, parent);
// ์ ์ฝ๋๋ ์๋์ ์ฝ๋์ ๋์ผํ๊ฒ ๋์ํ๋ค
// me.__proto__ = parent;
me.sayHello(); // Hi! My name is Lee
// constructor ํ๋กํผํฐ๊ฐ ์์ฑ์ ํจ์๋ฅผ ๊ฐ๋ฆฌํจ๋ค.
console.log(me.constructor === Person); // true
console.log(me.constructor === Object); // false
// ์์ฑ์ ํจ์์ prototype ํ๋กํผํฐ๊ฐ ๊ต์ฒด๋ ํ๋กํ ํ์
์ ๊ฐ๋ฆฌํจ๋ค.
console.log(Person.prototype === Object.getPrototypeOf(me)); // true
ํ๋กํ ํ์ ์ ์ง์ ๊ต์ฒดํ์ง ์๋ ๊ฒ์ด ์ข๋ค.
๊ฐ์ฒด instanceof ์์ฑ์ ํจ์
์ฐ๋ณ์ ์์ฑ์ ํจ์์ prototype์ ๋ฐ์ธ๋ฉ๋ ๊ฐ์ฒด๊ฐ ์ข๋ณ์ ๊ฐ์ฒด์ ํ๋กํ ํ์ ์ฒด์ธ ์์ ์กด์ฌํ๋ฉด true๋ก ํ๊ฐ๋๊ณ , ๊ทธ๋ ์ง ์์ ๊ฒฝ์ฐ์๋ false๋ก ํ๊ฐ๋๋ค.
instanceof ์ฐ์ฐ์๋ ํ๋กํ ํ์
์ constructor ํ๋กํผํฐ๊ฐ ๊ฐ๋ฆฌํค๋ ์์ฑ์ ํจ์๋ฅผ ์ฐพ๋ ๊ฒ์ด ์๋๋ผ ์์ฑ์ ํจ์์
prototype์ ๋ฐ์ธ๋ฉ๋ ๊ฐ์ฒด๊ฐ ํ๋กํ ํ์
์ฒด์ธ ์์ ์กด์ฌํ๋์ง ํ์ธํ๋ค.
Object.create ๋ฉ์๋๋ ๋ช
์์ ์ผ๋ก ํ๋กํ ํ์
์ ์ง์ ํ์ฌ ์๋ก์ด ๊ฐ์ฒด๋ฅผ ์์ฑ. Object.create ๋ฉ์๋๋ ๋ค๋ฅธ ๊ฐ์ฒด ์์ฑ ๋ฐฉ์๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก ์ถ์ ์ฐ์ฐ OrdinaryObjectCreate๋ฅผ ํธ์ถํ๋ค.
Object.create ๋ฉ์๋์ ์ฒซ ๋ฒ์จฐ ๋งค๊ฐ๋ณ์์๋ ์์ฑํ ๊ฐ์ฒด์ ํ๋กํ ํ์
์ผ๋ก ์ง์ ํ ๊ฐ์ฒด๋ฅผ ์ ๋ฌํ๋ค. ๋๋ฒ์งธ ๋งค๊ฐ๋ณ์์๋ ์์ฑํ ๊ฐ์ฒด์ ํ๋กํผํฐ ํค์ ํ๋กํผํฐ ํ๋กํผํฐ ๋์คํฌ๋ฆฝํฐ ๊ฐ์ฒด๋ก ์ด๋ค์ง ๊ฐ์ฒด๋ฅผ ์ ๋ฌํ๋ค. ์ด ๊ฐ์ฒด์ ํ์์ Object.defineProperties ๋ฉ์๋์ ๋ ๋ฒ์งธ ์ธ์์ ๋์ผํ๋ค. ๋ ๋ฒ์งธ ์ธ์๋ ์ต์
์ด๋ฏ๋ก ์๋ต ๊ฐ๋ฅ
// ํ๋กํ ํ์
์ด null์ธ ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ค. ์์ฑ๋ ๊ฐ์ฒด๋ ํ๋กํ ํ์
์ฒด์ธ์ ์ข
์ ์ ์์นํ๋ค.
// obj โ null
let obj = Object.create(null);
console.log(Object.getPrototypeOf(obj) === null); // true
// Object.prototype์ ์์๋ฐ์ง ๋ชปํ๋ค.
console.log(obj.toString()); // TypeError: obj.toString is not a function
// obj โ Object.prototype โ null
// obj = {};์ ๋์ผํ๋ค.
obj = Object.create(Object.prototype);
console.log(Object.getPrototypeOf(obj) === Object.prototype); // true
// obj โ Object.prototype โ null
// obj = { x: 1 };์ ๋์ผํ๋ค.
obj = Object.create(Object.prototype, {
x: { value: 1, writable: true, enumerable: true, configurable: true }
});
// ์ ์ฝ๋๋ ๋ค์๊ณผ ๋์ผํ๋ค.
// obj = Object.create(Object.prototype);
// obj.x = 1;
console.log(obj.x); // 1
console.log(Object.getPrototypeOf(obj) === Object.prototype); // true
const myProto = { x: 10 };
// ์์์ ๊ฐ์ฒด๋ฅผ ์ง์ ์์๋ฐ๋๋ค.
// obj โ myProto โ Object.prototype โ null
obj = Object.create(myProto);
console.log(obj.x); // 10
console.log(Object.getPrototypeOf(obj) === myProto); // true
// ์์ฑ์ ํจ์
function Person(name) {
this.name = name;
}
// obj โ Person.prototype โ Object.prototype โ null
// obj = new Person('Lee')์ ๋์ผํ๋ค.
obj = Object.create(Person.prototype);
obj.name = 'Lee';
console.log(obj.name); // Lee
console.log(Object.getPrototypeOf(obj) === Person.prototype); // true
Object.create ๋ฉ์๋๋ ์ฒซ ๋ฒ์งธ ๋งค๊ฐ๋ณ์์ ์ ๋ฌ๋ ๊ฐ์ฒด์ ํ๋กํ ํ์ ์ฒด์ธ์ ์ํ๋ ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ค. ์ฆ, ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ฉด์ ์ง์ ์ ์ผ๋ก ์์์ ๊ตฌํํ๋ ๊ฒ์ด๋ค. ์ด ๋ฉ์๋์ ์ฅ์ ์ ๋ค์๊ณผ ๊ฐ๋ค.
Es6์์๋ ๊ฐ์ฒด ๋ฆฌํฐ๋ด ๋ด๋ถ์์ __proto__ ์ ๊ทผ์ ํ๋กํผํฐ๋ฅผ ์ฌ์ฉํ์ฌ ์ง์ ์์์ ๊ตฌํํ ์ ์๋ค.
const myProto = { x: 10 };
// ๊ฐ์ฒด ๋ฆฌํฐ๋ด์ ์ํด ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ฉด์ ํ๋กํ ํ์
์ ์ง์ ํ์ฌ ์ง์ ์์๋ฐ์ ์ ์๋ค.
const obj = {
y: 20,
// ๊ฐ์ฒด๋ฅผ ์ง์ ์์๋ฐ๋๋ค.
// obj โ myProto โ Object.prototype โ null
__proto__: myProto
};
/** ์ ์ฝ๋๋ ์๋์ ๋์ผํ๋ค.
const obj = Object.create(myProto, {
y: { value: 20, writable: true, enumerable: true, configurable: true }
});
*/
console.log(obj.x, obj.y); // 10 20
console.log(Object.getPrototypeOf(obj) === myProto); // true
์ ์ ํ๋กํผํฐ/๋ฉ์๋๋ ์์ฑ์ ํจ์๋ก ์ธ์คํด์ค๋ฅผ ์์ฑํ์ง ์์๋ ์ฐธ์กฐ/ํธ์ถํ ์ ์๋ ํ๋กํผํฐ/๋ฉ์๋๋ฅผ ๋งํ๋ค.
// ์์ฑ์ ํจ์
function Person(name) {
this.name = name;
}
// ํ๋กํ ํ์
๋ฉ์๋
Person.prototype.sayHello = function () {
console.log(`Hi! My name is ${this.name}`);
};
// ์ ์ ํ๋กํผํฐ
Person.staticProp = 'static prop';
// ์ ์ ๋ฉ์๋
Person.staticMethod = function () {
console.log('staticMethod');
};
const me = new Person('april');
// ์์ฑ์ ํจ์์ ์ถ๊ฐํ ์ ์ ํ๋กํผํฐ/๋ฉ์๋๋ ์์ฑ์ ํจ์๋ก ์ฐธ์กฐ/ํธ์ถํ๋ค.
Person.staticMethod(); // staticMethod
// ์ ์ ํ๋กํผํฐ/๋ฉ์๋๋ ์์ฑ์ ํจ์๊ฐ ์์ฑํ ์ธ์คํด์ค๋ก ์ฐธ์กฐ/ํธ์ถํ ์ ์๋ค.
// ์ธ์คํด์ค๋ก ์ฐธ์กฐ/ํธ์ถํ ์ ์๋ ํ๋กํผํฐ/๋ฉ์๋๋ ํ๋กํ ํ์
์ฒด์ธ ์์ ์กด์ฌํด์ผ ํ๋ค.
me.staticMethod(); // TypeError: me.staticMethod is not a function
in ์ฐ์ฐ์๋ ๊ฐ์ฒด ๋ด์ ํน์ ํ๋กํผํฐ๊ฐ ์กด์ฌํ๋ ์ฌ๋ถ๋ฅผ ํ์ธํ๋ค.
/**
- key: ํ๋กํผํฐ ํค๋ฅผ ๋ํ๋ด๋ ๋ฌธ์์ด
- object : ๊ฐ์ฒด๋ก ํ๊ฐํ๋ ํํ์
*/
key in object
const person = {
name: 'Lee',
address: 'Seoul'
};
// person ๊ฐ์ฒด์ name ํ๋กํผํฐ๊ฐ ์กด์ฌํ๋ค.
console.log('name' in person); // true
// person ๊ฐ์ฒด์ address ํ๋กํผํฐ๊ฐ ์กด์ฌํ๋ค.
console.log('address' in person); // true
// person ๊ฐ์ฒด์ age ํ๋กํผํฐ๊ฐ ์กด์ฌํ์ง ์๋๋ค.
console.log('age' in person); // false
in ์ฐ์ฐ์ ๋์ ES6์์ ๋์ ๋ Reflect.has ๋ฉ์๋๋ฅผ ์ฌ์ฉํ ์๋ ์๋ค. Reflect.has ๋ฉ์๋๋ in ์ฐ์ฐ์์ ๋์ผํ๊ฒ ๋์
const person = { name: 'Lee'};
console.log(Reflect.has(person. 'name')); // true
console.log(Reflect.has(person. 'toString')); // true
Object.prototype.hasOwnProperty ๋ฉ์๋๋ฅผ ์ฌ์ฉํด๋ ๊ฐ์ฒด์ ํน์ ํ๋กํผํฐ๊ฐ ์กด์ฌํ๋์ง ํ์ธํ ์ ์๋ค.
console.log(person.hasOwnProperty('name')); // true
console.log(person.hasOwnProperty('age')); // true
์ธ์๋ก ์ ๋ฌ๋ฐ์ ํ๋กํผํฐ ํค๊ฐ ๊ฐ์ฒด ๊ณ ์ ์ ํ๋กํผํฐ ํค์ธ ๊ฒฝ์ฐ์๋ง true๋ฅผ ๋ฐํํ๊ณ ์์๋ฐ์ ํ๋กํ ํ์ ์ ํ๋กํผํฐ ํค์ธ ๊ฒฝ์ฐ false๋ฅผ ๋ฐํํ๋ค.
๊ฐ์ฒด์ ๋ชจ๋ ํ๋กํผํฐ๋ฅผ ์ํํ๋ฉฐ ์ด๊ฑฐํ๋ ค๋ฉด for.. in ๋ฌธ์ ์ฌ์ฉํ๋ค
for (๋ณ์์ ์ธ๋ฌธ in ๊ฐ์ฒด) {...}
๊ฐ์ฒด์ ํ๋กํ ํ์ ์ฒด์ธ ์์ ์กด์ฌํ๋ ๋ชจ๋ ํ๋กํ ํ์ ์ ํ๋กํผํฐ ์ค์์ ํ๋กํผํฐ ์ดํธ๋ฆฌ๋ทฐํธ [[Enumerable]]์ ๊ฐ์ด true์ธ ํ๋กํผํฐ๋ฅผ ์ํํ๋ฉฐ ์ด๊ฑฐํ๋ค.
๋ฐฐ์ด์๋ for..in ๋ฌธ์ ์ฌ์ฉํ์ง ๋ง๊ณ ์ผ๋ฐ์ ์ธ for ๋ฌธ์ด๋ for.. of ๋ฌธ ๋๋ Array.prototype.forEach ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๊ธฐ๋ฅผ ๊ถ์ฅํ๋ค.
๊ฐ์ฒด ์์ ์ ๊ณ ์ ํ๋กํผํฐ๋ง ์ด๊ฑฐํ๊ธฐ ์ํด์๋ for...in ๋ฌธ์ ์ฌ์ฉํ๋ ๊ฒ๋ณด๋ค Object.keys/values/entries ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ๊ถ์ฅ.
Object.keys ๋ฉ์๋๋ ๊ฐ์ฒด ์์ ์ ์ด๊ฑฐ ๊ฐ๋ฅํ ํ๋กํผํฐ ํค๋ฅผ ๋ฐฐ์ด๋ก ๋ฐํ
const person = {
name: 'Lee',
address: 'Seoul',
__proto__: { age: 20 }
};
console.log(Object.keys(person)); // ["name", "address"]
ES8์์ ๋์ ๋ Object.values ๋ฉ์๋๋ ๊ฐ์ฒด ์์ ์ ์ด๊ฑฐ ๊ฐ๋ฅํ ํ๋กํผํฐ ๊ฐ์ ๋ฐฐ์ด๋ก ๋ฐํ
console.log(Object.values(person)); // ["Lee", "Seoul"]
ES8์์ ๋์ ๋ Object.entries ๋ฉ์๋๋ ๊ฐ์ฒด ์์ ์ ์ด๊ฑฐ ๊ฐ๋ฅํ ํ๋กํผํฐ ํค์ ๊ฐ์ ์์ ๋ฐฐ์ด์ ๋ฐฐ์ด์ ๋ด์ ๋ฐํํ๋ค.
console.log(Object.entries(person)); // [["name","Lee"], ["address", "Seoul"]]
Object.entries(person).forEach(([key, value]) => console.log(key, value));
/*
name Lee
address Seoul
*/