Front-end/JS
์๋ฐ์คํฌ๋ฆฝํธ ํ๋กํ ํ์ Prototype (2)
ciocio
2022. 4. 4. 16:54
๐ ํ๋กํ ํ์ (๊ฐ์ฒด) ?
โ ๊ฐ์ฒด ๊ฐ ์์inheritance์ ๊ตฌํํ๊ธฐ ์ํ ํต์ฌ ๊ฐ๋ โ
โ ํ๋กํ ํ์ ์ ํ๋กํ ํ์ ์ ์ธ์ ๋ Object.prototype โ
ํ๋กํ ํ์ ์ ์ด๋ค ๊ฐ์ฒด์ ์์ ๊ฐ์ฒด(๋ถ๋ชจ ๊ฐ์ฒด)์ ์ญํ ์ ํ๋ ๊ฐ์ฒด๋ก,
๋ค๋ฅธ ๊ฐ์ฒด์ ๊ณต์ ํ๋กํผํฐ/๋ฉ์๋๋ฅผ ์ ๊ณตํ๋ค.
ํ๋กํ ํ์
์ ์์๋ฐ์ ํ์ ๊ฐ์ฒด(์์ ๊ฐ์ฒด)๋ ์์ ๊ฐ์ฒด์ ํ๋กํผํฐ/๋ฉ์๋๋ฅผ
๋ณธ์ธ์ ํ๋กํผํฐ/๋ฉ์๋์ฒ๋ผ ์์ ๋กญ๊ฒ ์ฌ์ฉํ ์ ์๋ค.
๐ ๊ฐ์ฒด ์์ฑ ๋ฐฉ์๊ณผ ํ๋กํ ํ์ ๊ฒฐ์
๐ฎ (์ง์ฌ์ผ๋ก ๋๋ฌด ๋ค์ํ) ๊ฐ์ฒด ์์ฑ ๋ฐฉ๋ฒ๋ค ...
โ ๊ฐ์ฒด ๋ฆฌํฐ๋ด
โ Object ์์ฑ์ ํจ์
โ ์์ฑ์ ํจ์ (new ์ฐ์ฐ์)
โ Object.create ๋ฉ์๋
โ ํด๋์ค(ES6)
๐ ๊ฐ์ฒด ๋ฆฌํฐ๋ด
๊ฐ์ฒด ๋ฆฌํฐ๋ด์ ์ํด ์์ฑ๋๋ ๊ฐ์ฒด์ ํ๋กํ ํ์ ์ Object.prototype ์ด๋ค.
const obj = {x: 1};
console.log(obj.constructor === Object); // true
console.log(obj.hasOwnProperty('x')); // true
// ๊ฐ์ฒด ๋ฆฌํฐ๋ด์ ์ํด ์์ฑ๋ obj ๊ฐ์ฒด๋ Object.prototype ์ ์์๋ฐ๋๋ค.
๐ Object ์์ฑ์ ํจ์
Object ์์ฑ์ ํจ์์ ์ํด ์์ฑ๋๋ ๊ฐ์ฒด์ ํ๋กํ ํ์ ์ Object.prototype ์ด๋ค.
const obj = new Object();
obj.x = 1;
console.log(obj.constructor === Object); // true
console.log(obj.hasOwnProperty('x')); // true
// Object ์์ฑ์ ํจ์์ ์ํด ์์ฑ๋ obj ๊ฐ์ฒด๋ Object.prototype ์ ์์๋ฐ๋๋ค.
// ๊ฐ์ฒด ๋ฆฌํฐ๋ด ๋ฐฉ์์ ๊ฐ์ฒด ๋ฆฌํฐ๋ด ๋ด๋ถ์ ํ๋กํผํฐ๋ฅผ ์ถ๊ฐํ์ง๋ง
// Object ์์ฑ์ ํจ์ ๋ฐฉ์์ ์ผ๋จ ๋น ๊ฐ์ฒด๋ฅผ ์์ฑํ ํ ํ๋กํผํฐ๋ฅผ ์ถ๊ฐํ๋ค.
๐ ์์ฑ์ ํจ์ (new ์ฐ์ฐ์)
์์ฑ์ ํจ์์ ์ํด ์์ฑ๋๋ ๊ฐ์ฒด์ ํ๋กํ ํ์ ์
์์ฑ์ ํจ์์ prototype ํ๋กํผํฐ์ ๋ฐ์ธ๋ฉ๋์ด ์๋ ๊ฐ์ฒด๋ค.
function Person(name){
this.name = name;
}
// ํ๋กํ ํ์
๋ฉ์๋
Person.prototype.sayHello = function(){
console.log(`Hi! My name is ${this.name}`);
};
const me = new Person('Lee');
const you = new Person('Kim');
me.sayHello(); // Hi! My name is Lee
you.sayHello(); // Hi! My name is Kim
// Person ์์ฑ์ ํจ์๋ฅผ ํตํด ์์ฑ๋ ๋ชจ๋ ๊ฐ์ฒด๋
// ํ๋กํ ํ์
์ ์ถ๊ฐ๋ sayHello ๋ฉ์๋๋ฅผ ์์๋ฐ์ ์์ ์ ๋ฉ์๋์ฒ๋ผ ์ฌ์ฉํ ์ ์๋ค.
๐ Object.create ๋ฉ์๋
Object.create ๋ฉ์๋๋ ํ๋กํ ํ์ ์ ๋ช ์์ ์ผ๋ก ์ง์ ํ์ฌ ์๋ก์ด ๊ฐ์ฒด๋ฅผ ์์ฑ.
Object.create ๋ฉ์๋์ ์ฒซ ๋ฒ์งธ ๋งค๊ฐ๋ณ์์๋ ์์ฑํ ๊ฐ์ฒด์ ํ๋กํ ํ์ ์ผ๋ก ์ง์ ํ ๊ฐ์ฒด๋ฅผ,
๋ ๋ฒ์งธ ๋งค๊ฐ๋ณ์์๋ ์์ฑํ ๊ฐ์ฒด์ property key ์ property descriptor ๋ก ์ด๋ค์ง ๊ฐ์ฒด๋ฅผ ์ ๋ฌ.
// Object.create(prototype, [, propertiesObject])
// ์ง์ ๋ ํ๋กํ ํ์
๋ฐ ํ๋กํผํฐ๋ฅผ ๊ฐ๋ ์๋ก์ด ๊ฐ์ฒด๋ฅผ ์์ฑํ์ฌ ๋ฐํํ๋ค.
// @param {Object} prototype - ์์ฑํ ๊ฐ์ฒด์ ํ๋กํ ํ์
์ผ๋ก ์ง์ ํ ๊ฐ์ฒด
// @param {Object} [propertiesObject] - ์์ฑํ ๊ฐ์ฒด์ ํ๋กํผํฐ๋ฅผ ๊ฐ๋ ๊ฐ์ฒด
// @returns {Object} ์ง์ ๋ ํ๋กํ ํ์
๋ฐ ํ๋กํผํฐ๋ฅผ ๊ฐ๋ ์๋ก์ด ๊ฐ์ฒด
// obj → null
let obj = Object.create(null);
console.log(Object.getPrototypeOf(obj) === null); // true
console.log(obj.toString()); // Object.prototype์ ์์๋ฐ์ง ๋ชปํจ.
// 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
// obj → myProto → Object.prototype → null
// ์์์ ๊ฐ์ฒด ์ง์ ์์๋ฐ๊ธฐ
const myProto = {x: 10};
obj = Object.create(myProto);
console.log(obj.x); // 10
console.log(Object.getPrototypeOf(obj) === myProto); // true
// obj → Person.prototype → Object.prototype → null
function Person(name){
this.name = name;
}
obj = Object.create(Person.prototype);
obj.name = 'Lee';
console.log(obj.name); // Lee
console.log(Object.getPrototypeOf(obj) === Person.prototype); // true
๐ Object.prototype ?
ํ๋กํ ํ์ ์ฒด์ธ์ ์ข ์ (end of prototype chain)
Object.prototype ์ ํ๋กํ ํ์ , ์ฆ [[Prototype]] ๋ด๋ถ ์ฌ๋กฏ์ ๊ฐ์ null ์ด๋ค.
ํ๋กํ ํ์ ์ฒด์ธ์ ์ข ์ ์ ์์นํ๋ ๊ฐ์ฒด๋ Object.prototype ์ built-in ๊ฐ์ฒด๋ฅผ ์ฌ์ฉํ ์ ์๋ค โ
๊ทธ๋์ Object.prototype ์ built-in ๋ฉ์๋๋ ๊ฐ์ ์ ์ผ๋ก ํธ์ถํ๋ ๊ฒ์ด ์ข๋ค.
const obj = Object.create(null);
obj.a = 1;
// console.log(obj.hasOwnProperty('a'));
// TypeError: obj.hasOwnProperty is not a function
// Object.prototype์ built-in ๋ฉ์๋๋ ๊ฐ์ ์ ์ผ๋ก ํธ์ถํ ๊ฒ โ
console.log(Object.prototype.hasOwnProperty.call(obj, 'a')); // true
๐ ํ๋กํ ํ์ ์ฒด์ธ vs ์ค์ฝํ ์ฒด์ธ
ํ๋กํ ํ์ ์ฒด์ธ์ ์์๊ณผ ํ๋กํผํฐ ๊ฒ์์ ์ํ ๋งค์ปค๋์ฆ
์ค์ฝํ ์ฒด์ธ์ ์๋ณ์ ๊ฒ์์ ์ํ ๋งค์ปค๋์ฆ
์๋ฐ์คํฌ๋ฆฝํธ ์์ง์ ํ๋กํ ํ์ ์ฒด์ธ์ ๋ฐ๋ผ ํ๋กํผํฐ/๋ฉ์๋๋ฅผ ๊ฒ์ํ๋ค.
์๋ฐ์คํฌ๋ฆฝํธ ์์ง์ ์ค์ฝํ ์ฒด์ธ์ ๋ฐ๋ผ ์๋ณ์๋ฅผ ๊ฒ์ํ๋ค.
ํ๋กํ ํ์ ์ฒด์ธ๊ณผ ์ค์ฝํ ์ฒด์ธ์ ์๋ก ํ๋ ฅํ์ฌ ํ๋กํผํฐ์ ์๋ณ์๋ฅผ ๊ฒ์ํ๋ ๋ฐ ์ฌ์ฉ๋๋ค.
๐ ์ค๋ฒ๋ผ์ด๋ฉ๊ณผ ํ๋กํผํฐ ์๋์
๐ ์ค๋ฒ๋ผ์ด๋ฉ overriding
์์ ํด๋์ค๊ฐ ๊ฐ์ง๊ณ ์๋ ๋ฉ์๋๋ฅผ ํ์ ํด๋์ค๊ฐ ์ฌ์ ์ํ์ฌ ์ฌ์ฉํ๋ ๋ฐฉ์
๐ ํ๋กํผํฐ ์๋์ property shadowing
์์ ๊ด๊ณ์ ์ํด ํ๋กํผํฐ๊ฐ ๊ฐ๋ ค์ง๋ ํ์
const Person = (function(){
// ์์ฑ์ ํจ์
function Person(name){
this.name = name;
}
// ํ๋กํ ํ์
๋ฉ์๋
Person.prototype.sayHi = function(){
console.log(`Hi, my name is ${this.name}`);
}
// ์์ฑ์ ํจ์ ๋ฐํ
return Person;
}());
const me = new Person('Lee');
// ์ธ์คํด์ค ๋ฉ์๋
me.sayHi = function(){
console.log(`Hey, my name is ${this.name}`);
};
me.sayHi(); // Hey, my name is Lee
// ์ธ์คํด์ค ๋ฉ์๋๊ฐ ํธ์ถ๋๋ค.
// ํ๋กํ ํ์
๋ฉ์๋๋ ์ธ์คํด์ค ๋ฉ์๋์ ์ํด ๊ฐ๋ ค์ง๋ค.
• ์ฐธ๊ณ ์๋ฃ
์๋ฐ์คํฌ๋ฆฝํธ DEEP DIVE - ์ด์ ๋ชจ
๋ฐ์ํ