2์ฃผ์ฐจ๊ฐ ์์๋์์ต๋๋ค.๐คฃ
Sprint03.Inheritance Pattern์ ์งํํ๊ธฐ ์ ์ ์ค์ํ ์์๋ค์ ๊ณต๋ถํฉ๋๋ค.
JavaScript๋ ํ๋กํ ํ์ ๊ธฐ๋ฐ์ ๊ฐ์ฒด ์งํฅํ ํ๋ก๊ทธ๋๋ฐ ์ธ์ด์ ๋๋ค.
์ด์ OOP(๊ฐ์ฒด ์งํฅ ํ๋ก๊ทธ๋๋ฐ)์ ๋ํด์ ์กฐ๊ธ ์๊ฒ ๋๋ฐ์, prototype ๊ธฐ๋ฐ์ ๋ฌด์์ ์๋ฏธํ ๊น์?
prototype์ ํด์ํด๋ณด๋ฉด ์ํ ์ด๋ผ๋ ์๋ฏธ๊ฐ ์์ต๋๋ค. ์ ๊ทธ๋ ๊ตฌ๋, ์ผ๋จ ๋์ด๊ฐ์๋ค.
ES6 ๋ฌธ๋ฒ์ด ๋์ ๋๊ธฐ ์ ์๋ JavaScript์๋ ํด๋์ค(Class)๊ฐ ์์์ต๋๋ค.
๊ทธ๋์ ๊ฐ์ฒด ์์ฑ์ ์ํด์ prototype์ ์ฌ์ฉํ์๋๋ฐ์.
์ฝ๋ ๋ถํฐ ํ๋ฒ ๋ด ์๋ค!
// EX.01
let singer = {
name: '๋คํ',
age: 22,
}
// ํฌ๋กฌ ์ฝ์์์ ํ
์คํธํ๋ฉด ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
singer {name: "๋คํ", age: 22}
> age: 22
> name: "๋คํ"
> __proto__: Object
// people๊ฐ์ฒด์ __proto__๋ Object๊ฐ์ฒด์ ํ๋กํ ํ์
๊ณผ ๊ฐ์ต๋๋ค.
console.log(singer.__proto__ === Object.prototype) // true
๊ฐ์ฒด๋ฅผ ์์ฑํ๋ฉด, ํ๋กํ ํ์ ์ด ๊ฒฐ์ ๋๊ณ , ์ฐ๋ฆฌ๋ ๊ทธ ํ๋กํ ํ์ ์ ๋ณ๊ฒฝํ ์ ์์ต๋๋ค!
๊ทธ๋ ๋ค๋ฉด ์ด๋ฅผ ์ ํฌ ์ ๋ง์ ๋ง๊ฒ ๋ณ๊ฒฝํ์ฌ, ์์์ ๊ตฌํํ๋ ๊ฒ์ด์ฃ !
์ด๋ฒ์ ์ผ๋ฐ ๊ฐ์ฒด๊ฐ ์๋ ํจ์ ๊ฐ์ฒด๋ฅผ ์์๋ณผ๊น์? ์ฌ๊ธฐ์๋ถํฐ ์กฐ๊ธ ํท๊ฐ๋ฆฝ๋๋ค!
// EX.02
function People(name, age) {
this.name = name;
this.age = age;
}
// ํฌ๋กฌ ์ฝ์์์ ํ
์คํธํ๋ฉด ๋ค์๊ณผ ๊ฐ์ต๋๋ค. (๋ถ๋ถ ์๋ต)
console.dir(People);
People(name, age)
> name: "People"
> prototype: {constructor: ฦ}
> __proto__: ฦ ()
// People ๊ฐ์ฒด์ ์ธ์คํด์ค๋ฅผ ์์ฑํฉ๋๋ค.
const dahyun = new People('๋คํ', 22);
// ํฌ๋กฌ ์ฝ์์์ ํ
์คํธํ๋ฉด ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
console.dir(dahyun);
People
> age: 22
> name: "๋คํ"
> __proto__: Object
ํจ์ ๊ฐ์ฒด People() ์์ newํค์๋๋ฅผ ์ฌ์ฉํ๋ฉด ์์ฑ์๊ฐ ๋๊ณ , ์ด๊ฒ์ผ๋ก ์์ฑํ ๊ฐ์ฒด๋ฅผ ์ธ์คํด์ค๋ผ๊ณ ํฉ๋๋ค.
ํจ์ ๊ฐ์ฒด์ ์ถ๋ ฅ๊ณผ ์ธ์คํด์ค ๊ฐ์ฒด์ ์ถ๋ ฅ์ ๋ณด๋ฉด, ์ธ์คํด์ค ๊ฐ์ฒด์ prototype
์ด ์์ต๋๋ค!
๊ทธ๋ ๋ค๋ฉด __proto__
๋ ๋ฌด์์ด๊ณ , prototype
๊ณผ ๋ฌด์์ด ๋ค๋ฅธ๊ฑธ๊น์?
๋จผ์ [[prototype]]
์ ์ดํดํ์
์ผ ํฉ๋๋ค! ๐๐ป
[[prototype]]
[[prototype]]
์ด๋ผ๋ ๋ด๋ถ ์ฌ๋กฏ์ด ์กด์ฌํฉ๋๋ค.[[prototype]]
์ ๊ฐ์ ํ๋กํ ํ์
๊ฐ์ฒด๋ก์, __proto__
๋ก ์ ๊ทผํ ์ ์์ต๋๋ค.__proto__
__proto__
์ ์ ๊ทผํ๋ฉด ๋ด๋ถ์ ์ผ๋ก Object.getPropertyOf()
๊ฐ ํธ์ถ๋์ด ํ๋กํ ํ์
๊ฐ์ฒด๋ฅผ ๋ฐํํฉ๋๋ค.People
์ด ํจ์ ๊ฐ์ฒด์ด๋ฉด ํจ์์ ํ๋กํ ํ์
์ ๊ฐ๋ฆฌํต๋๋ค.prototype
๊ทธ๋ผ, ์์์ ์์ฑํ ๊ฐ์ฒด๋ค์ ๋น๊ตํด๋ด ์๋ค!
// ๋๋ต์ ์ธ ๋ณ์ ์ค๋ช
let singer = { ... }
let People = function { ... }
let dahyun = new Person( ... )
// singer : ์ผ๋ฐ ๊ฐ์ฒด
singer.__proto__ === Object.prototype // true
singer.__proto__ === Function.prototype // false
// People : ํจ์ ๊ฐ์ฒด
People.__proto__ === Object.prototype // false
People.__proto__ === Function.prototype // true
// dahyun : ์ธ์คํด์ค ๊ฐ์ฒด
dahyun.__proto__ === Object.prototype // false
dahyun.__proto__ === Function.prototype // false
dahyun.__proto__ === People.prototype // true
๋ค๋ฅธ ์ธ์ด๋ฅผ ๊ณต๋ถํ์ จ๋ค๋ฉด class๋ฅผ ๋ฐฐ์ฐ์ค ๋ constructor๋ผ๋ ๊ฐ๋ ์ ๋ฐฐ์ฐ์ จ์ ํ ๋ฐ์. ์ด์ ๋น์ทํฉ๋๋ค.
ํ๋กํ ํ์ ๊ฐ์ฒด๋ constructor ํ๋กํผํฐ๋ฅผ ๊ฐ์ง๋ฉฐ, ์ด๋ ๊ฐ์ฒด์ ์ ์ฅ์์ ์์ ์ ์์ฑํ ๊ฐ์ฒด๋ฅผ ๊ฐ๋ฆฌํต๋๋ค.
์ญ์ ๋ง๋ณด๋จ ์ฝ๋๋ก ์ดํดํด ๋ด ์๋ค. ๐๐ป
์ฃผ์์ ์ค๋ช ์ ์ ๊ฒ ์ต๋๋ค :)
// ํจ์ ๊ฐ์ฒด๋ฅผ ์์ฑํฉ๋๋ค.
function People(name, age) {
this.name = name;
this.age = age;
}
// ์ธ์คํด์ค ๊ฐ์ฒด๋ฅผ ์์ฑํฉ๋๋ค.
const sohee = new People('์ํฌ', 29);
// ํฌ๋กฌ ์ฝ์์์ ์ถ๋ ฅํฉ๋๋ค.
console.dir(People)
People
> age: 29
> name: "์ํฌ"
> __proto__:
> constructor: ฦ People(name, age)
> __proto__: Object
// ๊ฒฐ๊ณผ 1 : People ์์ฑ์ ํจ์์ ์ํด ์์ฑ๋ ๊ฐ์ฒด๋ฅผ ์์ฑํ ๊ฐ์ฒด๋ People ์์ฑ์ ํจ์์
๋๋ค.
console.log(People.prototype.constructor === People) // true
// ๊ฒฐ๊ณผ 2 : ์ธ์คํด์ค๋ฅผ ์์ฑํ ๊ฐ์ฒด๋ People์
๋๋ค.
console.log(sohee.constructor === People) // true
// ๊ฒฐ๊ณผ 3 : ํจ์ ๊ฐ์ฒด๋ฅผ ์์ฑํ ๊ฐ์ฒด๋ Function ๊ฐ์ฒด์
๋๋ค.
console.log(People.constructor === Function) // true
JavaScript์์ ํน์ ๊ฐ์ฒด๋ ํ๋กํผํฐ์ ์ ๊ทผํ ๋, ํด๋น ๊ฐ์ฒด์ ๋์์ด ์๋ค๋ฉด [[prototype]]์ ํตํด ๋์์ ๊ฒ์ํฉ๋๋ค.
์ด๊ฒ์ด ์ฌ์ฌ ์ฒ๋ผ ์ฐ๊ฒฐ ๋์ด ์๋ค๊ณ ํ์ฌ Prototype Chain ์ด๋ผ๊ณ ํฉ๋๋ค.
๋ญ๊ฐ ๋ง์ด ์ด๋ ค์ด ๊ฒ๊ฐ์ง๋ง, ์ ํฌ๋ ์ด๋ฏธ ์์ฃผ ์ฌ์ฉํ๊ณ ์์ต๋๋ค!
๊ฐ์ฅ ์์ฃผ ์ฌ์ฉํ๋ ๋ฐฐ์ด์ ์๋ก ๋ค์ด๋ณผ๊น์?
// Array
Array.prototype
> concat: ฦ concat()
> constructor: ฦ Array()
> copyWithin: ฦ copyWithin()
> entries: ฦ entries()
> every: ฦ every()
> fill: ฦ fill()
> filter: ฦ filter()
> find: ฦ find()
> findIndex: ฦ findIndex()
> flat: ฦ flat()
...
๋ฐฐ์ด์์ ์์ฃผ ์ฌ์ฉํ๋ ๋ฉ์๋์ธ concat, every, fill ๋ฑ์ด ๋ชจ๋ prototype์ ๋ค์ด ์์ต๋๋ค.
๊ทธ๋ฐ๋ฐ ์ ํฌ๋ [1,2,3].prototype.concat ์ด ์๋ [1,2,3].concat์ ์ฌ์ฉํฉ๋๋ค.
์ด๋ฐ ๊ฒ๋ค๋ ๋ชจ๋ ํ๋กํ ํ์ ์ฒด์ธ์ ๋๋ค.
ํ๋กํ ํ์ ์ ์ด์ฌํ ๊ณต๋ถํ์ จ๋ค๋ฉด, ํ๋กํ ํ์ ์ฒด์ธ์ ์์ ๋ก ๊ฐ๋จํ๊ฒ ์ดํดํ์ค ์ ์์ต๋๋ค!
// prototype chain
const A = function() {}
A.prototype.log = "I'm here";
const B = function() {};
B.prototype = new A();
const C = function() {};
C.prototype = new B();
const message = new C();
console.log(message.log) // I'm here
๋ง์ง๋ง ์ค์ ๋จผ์ ๋ณด๋ฉด, C ์์ฑ์๋ก ๋ง๋ ์ธ์คํด์ค๊ฐ A.prototype.log๋ฅผ ์ฌ์ฉํฉ๋๋ค?!
์์ํ์ จ๊ฒ ์ง๋ง, C์ prototype์ log๊ฐ ์์ด ์ฐจ๋ก์ฐจ๋ก ์ฌ๋ผ๊ฐ๋ฉด์ ํ์ธํ์ฌ ๊ฐ์ ธ์ค๋ ๊ฒ์ ๋๋ค.
๋๋ฌด ๊ฐ๋จํ๋ฐ, ์ฃผ์ํ ์ ํ๋๋ง ์ง๊ณ ํ๋กํ ํ์ ์ฒด์ธ์ ๋ง์น๊ฒ ์ต๋๋ค.
// prototype chain
const A = function() {}
A.prototype.log = "I'm here";
const B = function() {};
B.prototype = new A();
const C = function() {};
C.prototype = new B();
C.prototype.log = 1;
const message = new C();
console.log(message.log) // 1
C์ prototype์ ๋ค๋ฅธ ๊ฐ์ ์ถ๊ฐ ํ์์ต๋๋ค.
๋ง์ง๋ง ์ค์ ๊ฒฐ๊ณผ์ ๊ฐ์ด, C์ prototype์ log๊ฐ ์กด์ฌํ๋ฏ๋ก 1 ์ ๋ฐ๋ก ๊ฐ์ ธ์ต๋๋ค.
๊ฐ์ฒด๋ฅผ ์์ฑํ๋ค...์ธ๊ฐ์? ๐
์ ๋ชจ๋ฅด๊ฒ ์ผ๋ MDN์์ ์์ ์ฝ๋๋ฅผ ๊ฐ์ ธ์๋ด ์๋ค!
// MDN : Object.create() - example
const person = {
isHuman: false,
printIntroduction: function () {
console.log(`My name is ${this.name}. Am I human? ${this.isHuman}`);
}
};
const me = Object.create(person);
me.name = "Matthew"; // "name" is a property set on "me", but not on "person"
me.isHuman = true; // inherited properties can be overwritten
me.printIntroduction();
// expected output: "My name is Matthew. Am I human? true"
๋ญ๊ฐ ๋ณต์ฌํ๋ ๋๋์ด ๋ญ๋๋ค. ์์ธํ ์ดํด๋ณด๊ฒ ์ต๋๋ค.
// person
person {isHuman: false, printIntroduction: ฦ}
// me
me {}
> __proto__:
> isHuman: false
> printIntroduction: ฦ ()
> __proto__: Object
// prototype check
me.__proto__ === person // true
๋น ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ ๊ฒ ๊ฐ์ง๋ง, me ๊ฐ์ฒด์ prototype์ person ๊ฐ์ฒด๋ฅผ ๊ฐ๋ฆฌํต๋๋ค.
๊ฐ์ ์ก์ ์ฑ๋ก, ์ ์๋ฅผ ์ดํด๋ณด๊ฒ ์ต๋๋ค.
Object.create()
1. ๊ฐ์ฒด์์ ๋ค๋ฅธ ๊ฐ์ฒด๋ก ์ง์ ์์์ ๊ตฌํํฉ๋๋ค.
2. ํด๋์ค ํจํด๊ณผ ๋ค๋ฅด๊ฒ new ํค์๋๋ฅผ ์ฌ์ฉํ์ง ์์ต๋๋ค.
3. ๊ฐ์ฒด ๋ฆฌํฐ๋ด ํจํด์๋ ์ฌ์ฉ ๊ฐ๋ฅํฉ๋๋ค.
์๋ฅผ ๋ค์ด๋ณด๊ฒ ์ต๋๋ค.
// Object.create() - example1
const animal = {
log: function() {
console.log(this.sound)
}
}
const dog = Object.create(animal);
console.log(dog) // {}
dog.sound = '๋ฉ๋ฉ'
dog.log(); // ๋ฉ๋ฉ
const cat = Object.create(animal);
console.log(cat) // {}
cat.sound = '๋ฅ๋ฅ'
cat.log(); // ๋ฅ๋ฅ
animal.isPrototypeOf(dog) // true
animal.isPrototypeOf(cat) // true
animal ๊ฐ์ฒด๋ฅผ ์์ฑํ์ฌ log๋ฉ์๋๋ฅผ ์ถ๊ฐํ์์ต๋๋ค.
Object.create(animal)์ ๋ฆฌํด๊ฐ์ dog์ ์ถ๊ฐํ์์ต๋๋ค.
console์ ์ฐ์ด๋ณด๋ฉด ๊ฒ์ผ๋ก ๋ณด๊ธฐ์ ๋น ๊ฐ์ฒด์ด์ง๋ง, __proto__
์ animal ๊ฐ์ฒด๋ฅผ ๊ฐ์ง๊ณ ์์ต๋๋ค.
๊ทธ๋์ animal๊ฐ์ฒด์ log๋ฅผ ์์๋ฐ์ dog.log ๋ก '๋ฉ๋ฉ', '๋ฅ๋ฅ'์ ์ถ๋ ฅํ ์ ์์ต๋๋ค.
๊ทธ๋ผ Object.create()์ ๋ด๋ถ๋ฅผ ํ์ธํด๋ด ์๋ค.
// MDN Object.create() - Polyfill
Object.create = function (proto) {
// ์์ธ ์ฒ๋ฆฌ ์๋ต
function F() {}
F.prototype = proto;
return new F();
};
์์ธ ์กฐ๊ฑด์ ์๋ตํ๋ ๋งค์ฐ ์งง์์ก์ต๋๋ค! โ๐ป
์ธ์๋ก proto๋ฅผ ๋ฐ์์ ์์ฑ์์ prototype์ proto๋ฅผ ๋ฃ๊ณ ๋ฆฌํดํ๊ณ ์๋ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค!
๋ค์ ์ฝ๋์์ Object.create()์ ๋ฌธ์ ์ ์ ๊ณ ์น๊ณ ๋ง๋ฌด๋ฆฌํ๊ฒ ์ต๋๋ค.
// Object.create() - example2
// 1. Human ํด๋์ค๋ฅผ ์์ฑํฉ๋๋ค.
let Human = function(name) {
this.name = name;
}
// 2. Human์ prototype์ sleep๋ฉ์๋๋ฅผ ์ถ๊ฐํฉ๋๋ค.
Human.prototype.sleep = function() {
console.log('zzz...')
};
// 3. ์ธ์คํด์ค ์์ฑ
let steve = new Human('steve');
// 4. Student ํด๋์ค๋ฅผ ์์ฑํฉ๋๋ค. ์ด๋, Human.call()๋ก this๋ฅผ ์ฐ๊ฒฐ์์ผ์ฃผ์ด์ผํฉ๋๋ค.
let Student = function(name) {
Human.call(this, name)
}
// 5. Object.create()์ ๊ฒฐ๊ณผ๋ฅผ Student.prototype์ผ๋ก ๋ฃ์ด์ค๋๋ค.
Student.prototype = Object.create(Human.prototype)
// 6. Student.prototype์ constructor๋ฅผ Student๊ฐ์ฒด๋ก ๋ง๋ค์ด์ค๋๋ค.
Student.prototype.constructor = Student;
// 7. learn ๋ฉ์๋๋ฅผ ์ถ๊ฐํฉ๋๋ค.
Student.prototype.learn = function() {
console.log('๋ฐฐ์ฐ๋์ค...')
};
// 8. john ์ธ์คํด์ค๋ฅผ ์์ฑํฉ๋๋ค.
let john = new Student('john');
john.learn() // ๋ฐฐ์ฐ๋์ค...
john.sleep() // zzz...
๋ง์ฝ 6๋ฒ ๊ณผ์ ์ ์๋ตํ๋ฉด Student.prototype์๋ constructor๊ฐ ์กด์ฌํ์ง์์ต๋๋ค.
๊ทธ๋์ Student.prototype.constructor๋ Student๋ฅผ ๊ฐ๋ฆฌ์ผ์ผ ํ๋ฏ๋ก ์ง์ ๋ฃ์ด์ค๋๋ค.
๊ทธ๋ฆฌ๊ณ 4๋ฒ์, new ํค์๋๋ก ์ธ์คํด์ค๋ฅผ ์์ฑํ ๋ Human์ this๋ Human์ ๊ฐ๋ฆฌํค์ง ์์ต๋๋ค.
๋ฐ๋ผ์ ์ง์ Human๊ณผ this๋ฅผ ์ฐ๊ฒฐ์์ผ ์ฃผ๋ ๊ฒ์ ๋๋ค.
ํท๊ฐ๋ฆฌ์ ๋ค๋ฉด ํ์ํ์ค ๋ ์ง์ ๋ฃ์ด๋ณด์๋ฉด ๊ธ๋ฐฉ ์ดํด๊ฐ ๋ ๊ฒ์ ๋๋ค ๐ค๐ป