ํ๋กํ ํ์ (prototype)
๐ ๊ธฐ๋ณธ ๊ฐ์ฒด์ __proto__
// ๋น ๊ฐ์ฒด ์์ฑ const obj = {}; console.log(obj.__proto__); // [Object: null prototype] {} (Object.prototype) console.log(obj.__proto__.__proto__); // null
obj๋ ๊ธฐ๋ณธ ๊ฐ์ฒด๋ก, Object ์์ฑ์๋ฅผ ํตํด ๋ง๋ค์ด์ก์ต๋๋ค. obj.__proto__๋ Object.prototype์ ์ฐธ์กฐํฉ๋๋ค. ์ด๋ ๋ชจ๋ ๊ธฐ๋ณธ ๊ฐ์ฒด์ ํ๋กํ ํ์ ์ ๋๋ค. Object.prototype์ __proto__๋ null๋ก, ํ๋กํ ํ์ ์ฒด์ธ์ ๋์ ๋ํ๋ ๋๋ค.
๐ ๋ฐฐ์ด ๊ฐ์ฒด์ __proto__
const arr = [1, 2, 3]; console.log(arr.__proto__); // [Array: null prototype] [] (Array.prototype) console.log(arr.__proto__.__proto__); // [Object: null prototype] {} (Object.prototype) console.log(arr.__proto__.__proto__.__proto__); // null
- arr๋ ๋ฐฐ์ด ๊ฐ์ฒด๋ก, Array ์์ฑ์๋ฅผ ํตํด ๋ง๋ค์ด์ก์ต๋๋ค.
- arr.__proto__๋ Array.prototype์ ์ฐธ์กฐํ๋ฉฐ, ๋ฐฐ์ด ๊ด๋ จ ๋ฉ์๋(push, pop ๋ฑ)๊ฐ ์ด ํ๋กํ ํ์ ์ ์ ์๋์ด ์์ต๋๋ค.
- Array.prototype์ __proto__๋ Object.prototype์ ์ฐธ์กฐํฉ๋๋ค. ๋ฐ๋ผ์ ๋ฐฐ์ด๋ ๊ธฐ๋ณธ์ ์ผ๋ก ๊ฐ์ฒด์ ์์ฑ์ ์์๋ฐ์ต๋๋ค.
๐ ์ปค์คํ ๊ฐ์ฒด์ ์์ฑ์ ํจ์
// ์์ฑ์ ํจ์ ์ ์ function Person(name) { this.name = name; } // Person.prototype์ ๋ฉ์๋ ์ถ๊ฐ Person.prototype.sayHello = function () { console.log("Hello, I'm ${this.name}"); }; // ๊ฐ์ฒด ์์ฑ const person = new Person("Alice"); // person์ __proto__ ํ์ธ console.log(person.__proto__); // Person { sayHello: [Function (anonymous)] } (Person.prototype) // Person.prototype์ __proto__ ํ์ธ console.log(person.__proto__.__proto__); // [Object: null prototype] {} (Object.prototype) // ํ๋กํ ํ์ ์ฒด์ธ์ ๋ฐ๋ผ ๋ฉ์๋ ํธ์ถ person.sayHello(); // Hello, I'm Alice
- Person์ ์์ฑ์ ํจ์๋ก, new Person()์ผ๋ก ์์ฑ๋ person ๊ฐ์ฒด์ __proto__๋ Person.prototype์ ์ฐธ์กฐํฉ๋๋ค.
- Person.prototype์๋ sayHello ๋ฉ์๋๊ฐ ์ ์๋์ด ์์ผ๋ฏ๋ก, person์ ์ด ๋ฉ์๋๋ฅผ ์์๋ฐ์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
- Person.prototype.__proto__๋ Object.prototype์ ์ฐธ์กฐํ๋ฉฐ, ์ฒด์ธ์ ๊ฒฐ๊ตญ null๋ก ๋๋ฉ๋๋ค.
__proto__๋ ๋นํ์ค ์์ฑ์ด์ง๋ง, ๋๋ถ๋ถ์ ๋ธ๋ผ์ฐ์ ์์ ๋๋ฒ๊น ์ฉ๋๋ก ์ ๊ทผ ๊ฐ๋ฅํฉ๋๋ค. ์ค์ ์ฝ๋์์๋ Object.getPrototypeOf(obj)๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ๊ถ์ฅ๋ฉ๋๋ค.
console.log(Object.getPrototypeOf(person) === Person.prototype); // true
- __proto__๋ ๊ฐ์ฒด์ ํ๋กํ ํ์ ๊ฐ์ ์ฐ๊ฒฐ์ ๋ณด์ฌ์ฃผ๋ฉฐ, ์ด๋ฅผ ํตํด ํ๋กํ ํ์ ์ฒด์ด๋์ด ๋์ํฉ๋๋ค.
ํ๋กํ ํ์ ์ฒด์ธ(prototype chain)
ํ๋กํ ํ์ ์ฒด์ด๋(prototype chaining)
ํ๋กํ ํ์ ๊ธฐ๋ฐ ์์(prototype-based inheritance)
- ๋์ ์ฐ๊ฒฐ: ๊ฐ์ฒด๋ __proto__๋ฅผ ํตํด ํ๋กํ ํ์ ๊ฐ์ฒด์ ์ฐ๊ฒฐ๋๋ฉฐ, ์ด ์ฐ๊ฒฐ์ ๋ฐํ์์ ๋์ ์ผ๋ก ์์ฑ์ด๋ ๋ฉ์๋๋ฅผ ์ฐธ์กฐํ ์ ์๊ฒ ํฉ๋๋ค.
- ๊ณต์ : ํ๋กํ ํ์ ์ ์ ์๋ ์์ฑ์ด๋ ๋ฉ์๋๋ ํด๋น ํ๋กํ ํ์ ์ ์์๋ฐ๋ ๋ชจ๋ ๊ฐ์ฒด๊ฐ ๊ณต์ ํฉ๋๋ค. ์ฆ, ๊ฐ ๊ฐ์ฒด๋ง๋ค ์๋ก ์์ฑ๋์ง ์๊ณ ํ๋กํ ํ์ ์์ ์ฐธ์กฐ๋ฉ๋๋ค.
- ์ฒด์ธ ๊ตฌ์กฐ: ์์์ ๋จ์ผ ๊ฐ์ฒด ์์ค์์ ๋๋๋ ๊ฒ์ด ์๋๋ผ, ํ๋กํ ํ์ ์ฒด์ธ์ ๋ฐ๋ผ ์ฌ๋ฌ ๋จ๊ณ๋ก ์ด์ด์ง ์ ์์ต๋๋ค.
๐ ๊ฐ์ฒด๋ฅผ ํตํด ์์์ผ๋ก ์ดํดํ๋ ์์
// ๋ถ๋ชจ ์ญํ ์ ํ ํ๋กํ ํ์ ๊ฐ์ฒด const animal = { eat: function() { console.log("${this.name} is eating!"); } }; // ์์ ๊ฐ์ฒด ์์ฑ ๋ฐ ์์ ์ค์ const dog = { name: "Dog" }; Object.setPrototypeOf(dog, animal); // ์์๋ฐ์ ๋ฉ์๋ ํธ์ถ dog.eat(); // ์ถ๋ ฅ: "Dog is eating!" // ํ๋กํ ํ์ ํ์ธ console.log(dog.__proto__ === animal); // ์ถ๋ ฅ: true
- dog ๊ฐ์ฒด๋ animal ๊ฐ์ฒด๋ฅผ ํ๋กํ ํ์ ์ผ๋ก ์์๋ฐ์์ต๋๋ค.
- dog ์์ฒด์๋ eat ๋ฉ์๋๊ฐ ์์ง๋ง, __proto__๋ฅผ ํตํด animal์ eat ๋ฉ์๋๋ฅผ ์์๋ฐ์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
๐ ์์ฑ์ ํจ์๋ฅผ ํตํ ์์ ์์
// ๋ถ๋ชจ ์์ฑ์ ํจ์ function Animal(name) { this.name = name; } Animal.prototype.eat = function() { console.log("${this.name} is eating!"); }; // ์์ ์์ฑ์ ํจ์ function Dog(name) { Animal.call(this, name); // Animal์ ์์ฑ ์์ } Object.setPrototypeOf(Dog.prototype, Animal.prototype); // ํ๋กํ ํ์ ์์ // ๊ฐ์ฒด ์์ฑ const myDog = new Dog("Max"); // ์์๋ฐ์ ๋ฉ์๋ ํธ์ถ myDog.eat(); // ์ถ๋ ฅ: "Max is eating!" // ํ๋กํ ํ์ ์ฒด์ธ ํ์ธ console.log(myDog.__proto__ === Dog.prototype); // ์ถ๋ ฅ: true console.log(myDog.__proto__.__proto__ === Animal.prototype); // ์ถ๋ ฅ: true
- Dog๋ Animal์ ํ๋กํ ํ์ ์ ์์๋ฐ์ eat ๋ฉ์๋๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
- Animal.call(this, name)์ผ๋ก name ์์ฑ์ ์์๋ฐ๊ณ , Object.setPrototypeOf๋ก ํ๋กํ ํ์ ์ฒด์ธ์ ์ฐ๊ฒฐํด ๋ฉ์๋๊น์ง ์์๋ฐ์์ต๋๋ค.
- ์ด๋ ์ ํต์ ์ธ ์์์ฒ๋ผ "๋ถ๋ชจ(Animal)๋ก๋ถํฐ ์์(Dog)์ด ๊ธฐ๋ฅ์ ๋ฌผ๋ ค๋ฐ๋๋ค"๋ ๊ฐ๋ ์ผ๋ก ์ดํดํ ์ ์์ต๋๋ค.
์์์ผ๋ก ๋ณผ ์ ์๋ ์ด์
- ์์ฑ๊ณผ ๋ฉ์๋ ์ฌ์ฌ์ฉ: ๊ฐ์ฒด๊ฐ ํ๋กํ ํ์ ์์ ์์ฑ๊ณผ ๋ฉ์๋๋ฅผ ๋ฌผ๋ ค๋ฐ์ ์ฌ์ฉํ๋ฏ๋ก, ์ฝ๋ ์ค๋ณต์ ์ค์ด๊ณ ์ฌ์ฌ์ฉ์ฑ์ ๋์ด๋ ์์์ ๋ชฉ์ ์ ์ถฉ์กฑํฉ๋๋ค.
- ๊ณ์ธต ๊ตฌ์กฐ: ํ๋กํ ํ์ ์ฒด์ธ์ ํตํด ๋ถ๋ชจ-์์ ๊ด๊ณ์ ์ ์ฌํ ๊ณ์ธต ๊ตฌ์กฐ๋ฅผ ํ์ฑํฉ๋๋ค.
- ํ์ฅ ๊ฐ๋ฅ์ฑ: ํ๋กํ ํ์ ์ ์๋ก์ด ๊ธฐ๋ฅ์ ์ถ๊ฐํ๋ฉด ์ด๋ฅผ ์์๋ฐ๋ ๋ชจ๋ ๊ฐ์ฒด๊ฐ ๊ทธ ๊ธฐ๋ฅ์ ์ฌ์ฉํ ์ ์์ด, ์์์ ์ ์ฐ์ฑ์ ๋ณด์ฌ์ค๋๋ค.
์ฃผ์ํ ์ ์๋ฐ์คํฌ๋ฆฝํธ์ ์์์ ํด๋์ค ๊ธฐ๋ฐ ์ธ์ด์ฒ๋ผ ๊ณ ์ ๋ ๊ณ์ธต ๊ตฌ์กฐ๋ฅผ ๋ฐ๋ฅด์ง ์๊ณ , ๊ฐ์ฒด ๊ฐ์ ๋์ ์ฐ๊ฒฐ(__proto__)์ ์์กดํฉ๋๋ค. ์์๋ฐ์ ์์ฑ์ด๋ ๋ฉ์๋๋ ์ค์ ๋ก ๊ฐ์ฒด ์์ฒด์ ๋ณต์ฌ๋๋ ๊ฒ์ด ์๋๋ผ ์ฐธ์กฐ๋๋ ๊ฒ์ด๋ฏ๋ก, ํ๋กํ ํ์ ์ ์์ ํ๋ฉด ๋ชจ๋ ์์๋ฐ์ ๊ฐ์ฒด์ ์ํฅ์ ๋ฏธ์นฉ๋๋ค.