prototype inheritance - Lee-hyuna/33-js-concepts-kr GitHub Wiki
μν μμ
μλ¬Έ: Prototypal inheritance
νλ‘κ·Έλλ°μμ μ’ μ’ λ¬΄μΈκ°λ₯Ό νμ₯νκΈ°λ₯Ό μνλ€.
μλ₯Όλ€μ΄, μμ±λ€κ³Ό λ©μλλ₯Ό κ°μ§ user
κ°μ²΄κ° μκ³ μ΄λ₯Ό μ½κ° λ³ννμ¬ admin
κ³Ό guest
λ₯Ό λ§λλ €κ³ ν λ user
μ μλ κ²λ€μ μ¬μ¬μ©νκ³ μΆμ κ²μ΄λ€. μ¦, λ©μλλ₯Ό 볡μ¬/μ¬μμ±νμ§ μκ³ μλ‘μ΄ κ°μ²΄λ₯Ό λ§λ€κ³ μΆμ κ²μ΄λ€.
μ΄λ₯Ό μν΄ μν μμ(Prototypal inheritance)μ΄λΌλ νΉμ§μ΄ μ‘΄μ¬νλ€.
Prototype
μλ°μ€ν¬λ¦½νΈμ κ°μ²΄(object)λ null
μ΄κ±°λ λ€λ₯Έ κ°μ²΄λ₯Ό μ°Έμ‘°νλ μ¨κ²¨μ§ μμ±μΈ [Prototype](/Lee-hyuna/33-js-concepts-kr/wiki/Prototype)
μ κ°μ§κ³ μλ€. (μ€ν λ¬Έμμ μ νμλ―μ΄). μ΄ κ°μ²΄λ₯Ό "νλ‘ν νμ
"μ΄λΌ νλ€.
νλ‘ν νμ
μ μ½κ° λ§λ²κ°λ€. object
μμ μμ± κ°μ μ κ·Όνλ €κ³ ν λ, ν΄λΉ κ°μ΄ μ‘΄μ¬νμ§ μμΌλ©΄ μλ°μ€ν¬λ¦½νΈλ μλμ μΌλ‘ κ·Έ κ°μ²΄μ νλ‘ν νμ
(μν)μμ κ·Έ κ°μ κ°μ Έμ¨λ€. λ§μ μΈμ΄λ€μ νΉμ§λ€κ³Ό νλ‘κ·Έλλ° κΈ°μ μ΄ μ΄λ₯Ό ν λλ‘νλ€.
[Prototype](/Lee-hyuna/33-js-concepts-kr/wiki/Prototype)
μμ±μ λ΄λΆμ μΌλ‘ μ¨κ²¨μ Έ μλλ°, μ΄λ₯Ό μ€μ νλ λ°©λ²μ μ¬λ¬κ°μ§κ° μ‘΄μ¬νλ€.
κ·Έ μ€ νλκ° μλμ κ°μ΄ __proto__
λ₯Ό μ¬μ©νλ κ²μ΄λ€.
let animal = {
eats: true
};
let rabbit = {
jumps: true
};
rabbit.__proto__ = animal;
__proto__
λ[Prototype](/Lee-hyuna/33-js-concepts-kr/wiki/Prototype)
μ μν historical getter/setterμ΄λ€.
__proto__
μ[Prototype](/Lee-hyuna/33-js-concepts-kr/wiki/Prototype)
κ³Ό _κ°μ§ μλ€_λ κ²μ κΈ°μ΅ν΄λΌ.__proto__
λ[Prototype](/Lee-hyuna/33-js-concepts-kr/wiki/Prototype)
μ getter/setterμ΄λ€.
__proto__
λ μμ¬μ μ΄μ λ‘ μ‘΄μ¬νλλ°, νλ μΈμ΄μμλObject.getPrototypeOf/Object.setPrototypeOf
κ°μ ν¨μ ννλ‘ λ체λμλ€. μ’ λ λμ€μ λ체λ μ΄μ μ ν΄λΉ ν¨μλ₯Ό μ΄ν΄ λ³Ό κ²μ΄λ€.μ€νμ λ°λ₯΄λ©΄
__proto__
λ λΈλΌμ°μ μ μν΄μλ§ μ§μλμ΄μΌ νμ§λ§, μ¬μ€ μλ² μΈ‘μ λΉλ‘―ν λͺ¨λ νκ²½μμ μ§μνλ€. μ§κΈλΆν΄__proto__
νκΈ°λ²μ΄ μ‘°κΈ λ μ§κ΄μ μΌλ‘ λͺ λ°±νλ―λ‘ μμ μμ μ¬μ©ν κ²μ΄λ€.
rabbit
μ μ΄λ€ μμ±μ μ°Ύλλ° κ·Έκ²μ΄ μλ€λ©΄, μλ°μ€ν¬λ¦½νΈλ μλμ μΌλ‘ animal
μμ μ°Ύμ κ²μ΄λ€.
μλ₯Ό λ€μ΄:
let animal = {
eats: true
};
let rabbit = {
jumps: true
};
rabbit.__proto__ = animal; // (*)
// we can find both properties in rabbit now:
alert( rabbit.eats ); // true (**)
alert( rabbit.jumps ); // true
μ¬κΈ°(*)
κ° νμλ μ€μμ rabbit
μ νλ‘ν νμ
(μν)μ animal
μ€μ νκ³ μλ€.
μ΄ν, alert
μ΄ (**)
μμ rabbit.eats
μμ±μ μ½μΌλ € ν λ, rabbit
μλ ν΄λΉ μμ±μ΄ μ‘΄μ¬νμ§ μλλ€. λ°λΌμ μλ°μ€ν¬λ¦½νΈλ [Prototype](/Lee-hyuna/33-js-concepts-kr/wiki/Prototype)
μ°Έμ‘°λ₯Ό λ°λΌκ° animal
μμ ν΄λΉ μμ±μ μ°ΎμλΈλ€. (μ΄λ μλμλΆν° μ°Ύλλ€).
μ΄κ²μ "animal
μ rabbit
μ νλ‘ν νμ
"λΌκ³ νκ±°λ "rabbit
μ animal
μΌλ‘ λΆν° νν λ‘νμ
μμμ λ°λλ€."λΌκ³ ν μ μλ€.
κ·Έλμ animal
μ΄ λ§μ μ μ©ν μμ±λ€κ³Ό λ©μλλ₯Ό κ°μ§κ³ μλ€λ©΄, rabbit
μμ μλμΌλ‘ μ¬μ©ν μ μκ² λλ€. κ·Έλ¬ν μμ±λ€μ "inherited" λΌκ³ λΆλ₯Έλ€.
animal
μ νΉμ λ©μλκ° μ‘΄μ¬νλ©΄, rabbit
μμλ νΈμΆν μ μλ€.:
let animal = {
eats: true,
walk() {
alert("Animal walk");
}
};
let rabbit = {
jumps: true,
__proto__: animal
};
// walk is taken from the prototype
rabbit.walk(); // Animal walk
μλμ κ°μ΄, ν΄λΉ λ©μλ(walk
)λ μλμ μΌλ‘ νλ‘ν νμ
μμ κ°μ Έμμ§λ€.
μ΄λ¬ν νμμ νλ‘ν νμ 체μΈμ΄λΌ νλλ°, νλ‘ν νμ 체μΈμ λ κΈΈμ΄μ§ μ μλ€.
let animal = {
eats: true,
walk() {
alert("Animal walk");
}
};
let rabbit = {
jumps: true,
__proto__: animal
};
let longEar = {
earLength: 10,
__proto__: rabbit
};
// walk is taken from the prototype chain
longEar.walk(); // Animal walk
alert(longEar.jumps); // true (from rabbit)
λ¨, λκ°μ§μ μ μ½μ¬νμ΄ μλ€.
- μ°Έμ‘°λ μνμ΄ λμ΄μ μλλ€.
__proto__
λ₯Ό μννλλ‘ ν λΉνλ©΄ μλ°μ€ν¬λ¦½νΈλ μ€λ₯λ₯Ό λμ§ κ²μ΄λ€. __proto__
μ κ°μ κ°μ²΄μ΄κ±°λnull
μ΄μ΄μΌνλ€. μμ κ°κ³Ό κ°μ λ€λ₯Έ νμ λ€μ 무μλλ€.
λν λΉμ°νκ²λ [Prototype](/Lee-hyuna/33-js-concepts-kr/wiki/Prototype)
μ μ€μ§ νκ°λ§ κ°μ§ μ μλ€. ν κ°μ²΄λ λκ°μ κ°μ²΄μμ λμμ μμ λ°μ μ μλ€.
κ°μ μ°λ κ²μ νλ‘ν νμ μ μ¬μ©νμ§ μκΈ°
νλ‘ν νμ μ μ½κΈ° μ μ© μμ±μ΄λ€.
κ·Έλ¬λ μμ±μ μ°κ³ /μ½λ μ°μ°μ κ°μ²΄μ μ§μ μ μΌλ‘ μ μ©ν μ μλ€.
μλμ μλ₯Ό 보면, walk
λ©μλλ₯Ό rabbit
μ ν λΉνκ³ μλ€.
let animal = {
eats: true,
walk() {
/* this method won't be used by rabbit */
}
};
let rabbit = {
__proto__: animal
};
rabbit.walk = function() {
alert("Rabbit! Bounce-bounce!");
};
rabbit.walk(); // Rabbit! Bounce-bounce!
μ΄μ , rabbit.walk()
μ νΈμΆμ νλ‘ν νμ
μ μ¬μ©νμ§ μκ³ κ°μ²΄μμ μ¦μ μ°Ύμμ Έ μ€νλ κ²μ΄λ€.
μ΄λ λ°μ΄ν° μμ±λ§μ μν κ²μ΄μ§ μ κ·Όμλ₯Ό μν κ²μ μλλ€. μμ±μ΄ getter/setter λΌλ©΄ ν¨μμ²λΌ λμνλ€. getter/setterλ νλ‘ν νμ μ λ°λΌλ³Έλ€.
κ·Έλ° μ΄μ λ‘, admin.fullName
μ μλ μ½λμ κ°μ΄ μ μμ μΌλ‘ λμνλ€.
let user = {
name: "John",
surname: "Smith",
set fullName(value) {
[this.name, this.surname] = value.split(" ");
},
get fullName() {
return `${this.name} ${this.surname}`;
}
};
let admin = {
__proto__: user,
isAdmin: true
};
alert(admin.fullName); // John Smith (*)
// setter triggers!
admin.fullName = "Alice Cooper"; // (**)
(*)
λΌμΈμ admin.fullName
μμ±μ user
νλ‘ν νμ
μμ getterλ₯Ό κ°μ§κ³ μλ€, κ·Έλμ νΈμΆλ κ²μ΄λ€. κ·Έλ¦¬κ³ (**)
λΌμΈμ μμ±μ νλ‘ν νμ
μμ setterλ₯Ό κ°μ§κ³ μλ€. λλ¬Έμ νΈμΆλ κ²μ΄λ€.
"this" κ°
μμ μμ μμ ν₯λ―Έλ‘μ΄ μ§λ¬Έμ΄ λμ¬ μ μλ€: set fullName(valuie)
μμ this
λ μ΄λ€ κ°μ κ°μ§κ³ μμκΉ? μ½λ μ μ΄λ μμΉμμ this.name
κ³Ό this.surname
μ μ°μ¬μ‘μκΉ? user
λλ admin
? λ΅μ κ°λ¨νλ€.
this
λ νλ‘ν νμ
μ μν΄ μ ν μν₯μ λ°μ§ μλλ€.
λ©μλκ° μ΄λμ λ°κ²¬ λλκ°μ, λ©μλ νΈμΆμμ this
λ μΈμ λ .
μ°μ° μμ μλ κ°μ²΄λ₯Ό κ°λ₯΄ν¨λ€.
κ·Έλμ, setterκ° admin.fullName=
λ₯Ό νΈμΆν λ user
κ° μλ admin
μ this
λ‘ μ¬μ©νλ€.
μ΄κ±΄ μ¬μ€ λ§€μ° λ§€μ° μ€μν μ¬μ€μ΄λ€. μλνλ©΄ λ§μ λ©μλλ₯Ό κ°μ§ κ°μ²΄λ₯Ό κ°μ§κ³ μκ³ μ΄ κ°μ²΄λ₯Ό μμλ°μ κ°μ²΄κ° μ‘΄μ¬νλ€κ³ μκ°ν΄λ³΄μ. κ·Έ νμ λΆλͺ¨ κ°μ²΄μ λ©μλλ₯Ό μμλ κ°μ²΄μμ μ€ννλ€λ©΄, λΆλͺ¨ κ°μ²΄μ μνκ°μ΄ μλ μμ κ°μ²΄μ μν κ°μ μμ ν κ²μ΄λ€,
μλ₯Ό λ€μ΄, animal
κ° "λ©μλ μ μ₯μ"λΌκ³ κ°μ νκ³ , rabbit
μ μ΄κ²μ μ¬μ©νλ€ μΉμ.
rabbit.sleep()
νΈμΆμ this.isSleeping
μ rabbit
κ°μ²΄μ ν λΉν κ²μ΄λ€.
// animal has methods
let animal = {
walk() {
if (!this.isSleeping) {
alert(`I walk`);
}
},
sleep() {
this.isSleeping = true;
}
};
let rabbit = {
name: "White Rabbit",
__proto__: animal
};
// modifies rabbit.isSleeping
rabbit.sleep();
alert(rabbit.isSleeping); // true
alert(animal.isSleeping); // undefined (no such property in the prototype)
κ²°κ³Όλ κ·Έλ¦Όκ³Ό κ°λ€.
animal
λ‘ λΆν° μμν bird
λ snake
λ±μ κ°μ²΄λ₯Ό κ°μ§κ³ μλ€κ³ κ°μ ν΄λ³΄μ. μ΄ κ²λ€λ μμ animal
μ λ©μλλ€μ μ κ·Όν μ μμ κ²μ΄λ€. νμ§λ§ κ° λ©μλμ this
λ animal
μ΄ μλλΌ .
μ΄μ μ νΈμΆ μμ μ νκ°λ κ° κ°μ²΄μ λμν κ²μ΄λ€. κ·Έλμ this
μ λ°μ΄ν°λ₯Ό μ μ₯ν λ, μ΄ κ°μ²΄λ€μ μ μ₯νλ κ²μ΄λ€.
κ²°κ³Όμ μΌλ‘ λ©μλλ 곡μ λμ§λ§, κ°μ²΄μ μν κ°μ 곡μ λμ§ μλλ€.
forβ¦in loop
for..in
μ μμλ°μ μμ±λ€λ μννλ€.
μλ₯Ό λ€μ΄:
let animal = {
eats: true
};
let rabbit = {
jumps: true,
__proto__: animal
};
// Object.keys only return own keys
alert(Object.keys(rabbit)); // jumps
// for..in loops over both own and inherited keys
for(let prop in rabbit) alert(prop); // jumps, then eats
μνλ κ²°κ³Όκ° μ΄κ²μ΄ μλ κ²μ΄λ€. μμ λ°μ μμ±μ μ μΈνκ³ μΆμ κ²μ΄λ€. μ΄λ₯Ό μν λ΄μ₯ λ©μλ obj.hasOwnProperty(key)κ° μλ€. μ΄ λ©μλλ μμ± μ΄λ¦ key
κ° obj
κ° κ°μ§ μμ±μ΄λ©΄ (μμ λ°μ κ²μ΄ μλλΌ), true
λ₯Ό λ°ννλ€.
λ°λΌμ μμλ μμ±λ€μ κ±Έλ¬λΌ μ μλ€.
let animal = {
eats: true
};
let rabbit = {
jumps: true,
__proto__: animal
};
for(let prop in rabbit) {
let isOwn = rabbit.hasOwnProperty(prop);
if (isOwn) {
alert(`Our: ${prop}`); // Our: jumps
} else {
alert(`Inherited: ${prop}`); // Inherited: eats
}
}
λ€μκ³Ό κ°μ μμ 체μΈμ΄ μλ€. rabbit
μ animal
μ μμ λ°κ³ animal
μ Obejct.prototype
μΌλ‘ λΆν° μμ λ°μ κ²μ΄λ€. μλνλ©΄ κΈ°λ³Έμ μΌλ‘, animal
μ 리ν°λ΄ κ°μ²΄ {...}
μ΄κΈ° λλ¬Έμ΄λ€. κ·Έλ¦¬κ³ Obejct.prototype
μ null
μ λ°λΌλ³Έλ€.
μ¬κΈ°μμ μ¬λ―Έμλ μ μ΄ μλ€. rabbit.hasOwnProperty
λ μ΄λμ λμ¨ κ²μΌκΉ? μ°λ¦¬λ ν΄λΉ λ©μλλ₯Ό μ μνμ§ μμλ€. μμ 체μΈμ 보면, Object.prototype.hasOwnProperty
μ μν΄ μ 곡λ λ©μλμμ μ μ μλ€. μ¦, μ΄κ±΄ μμ λ°μ κ²μ΄λ€.
κ·Έλ¬λ μμλ μμ±λ€λ λμ΄νλ for..in
λ°λ³΅μμ, μ eats
μ΄λ jumps
μ²λΌ hasOwnProperty
κ° λ³΄μ΄μ§ μμκΉ?
λ΅μ κ°λ¨νλ€. hasOwnProperty
λ μ΄κ±°κ°λ₯(enumerable)ν μμ±μ΄ μλκΈ° λλ¬Έμ΄λ€. μ΄μ κ°μ΄ Object.prototype
μμ±λ€μ enumerable:false
κ°μ κ°μ§κ³ μλ€. μ΄κ² λ°λ‘ λ°λ³΅μμ 보μ΄μ§ μλ μ΄μ μ΄λ€.
λͺ¨λ λ€λ₯Έ λ°λ³΅ λ©μλλ€μ μμ μμ±μ 무μνλ€
Object.keys
,Object.values
μ κ°μ key / valueλ₯Ό κ°μ Έμ€λ λ©μλλ€μ μμλ κ°μ 무μνλ€.μ΄λ€μ μ€μ§ κ°μ²΄ μμ²΄κ° κ°μ§ κ°μ κ°μ Έμ¨λ€,
μμ½
- μλ°μ€ν¬λ¦½νΈμμ, λͺ¨λ κ°μ²΄λ μ¨κ²¨μ§
[Prototype](/Lee-hyuna/33-js-concepts-kr/wiki/Prototype)
μμ±μ κ°λλ€. κ·Έλ¦¬κ³ μ΄ μμ±μ λλ€λ₯Έ κ°μ²΄μ΄κ±°λnull
μ΄λ€. obj.__proto__
λ₯Ό μ¬μ©νμ¬ μ΄ μμ±μ μ κ·Όν μ μλ€.[Prototype](/Lee-hyuna/33-js-concepts-kr/wiki/Prototype)
μ μν΄ μ°Έμ‘°λλ κ°μ²΄λ₯Ό "νλ‘ν νμ (μν)"μ΄λΌκ³ νλ€.obj
μ μμ±μ μ½κ±°λ λ©μλλ₯Ό νΈμΆνκ³ μΆμλ° μ‘΄μ¬νμ§ μλλ€λ©΄, μλ°μ€ν¬λ¦½νΈλ νλ‘ν νμ μμ κ·Έκ²μ μ°ΎμΌλ € ν κ²μ΄λ€.- μ½κΈ°/μ§μ°κΈ° μ°μ°μ κ°μ²΄μ μ§μ μ μΌλ‘ μ μ©λλ€. νλ‘ν νμ μ μ¬μ©νμ§ μλλ€.(setterκ° μλ λ°μ΄ν° μμ±μ΄λΌ κ°μ νμ κ²½μ°).
obj.method()
λ₯Ό νΈμΆνκ³ , ν΄λΉmethod
κ° νλ‘ν νμ μμ κ°μ Έμ¨ κ²μ΄λΌλ©΄,this
λ μ¬μ νobj
λ₯Ό ν¨λ€. μ¬μ§μ΄ λ©μλλ€μ΄ μμλ¬λ€ νλλΌλ λ©μλλ€μ μΈμ λ νμ¬ κ°μ²΄μ μ μ©λ κ²μ λλ€.for..in
루νλ μμ μ κ°κ³Ό μμλ κ°μ λ°λ³΅νλ€. κ·Έ μΈμ key/valueλ₯Ό κ°μ Έμ€λ λ€λ₯Έ λͺ¨λ λ©μλλ€μ μ€μ§ κ·Έ μμ μ κ°μ²΄μ μμ±λ§ κ°μ Έμ¨λ€.