- Published on
Javascript Prototype
- Author
- Name
- yceffort
Table of Contents
νλ‘ν νμ
μμμ΄λΌλ κ΄μ μμ λ΄€μ λ, μλ°μ€ν¬λ¦½νΈμ μ μΌν μμ±μλ κ°μ²΄ λΏμ΄λ€. λͺ¨λ κ°μ²΄λ [[prototype]]
μ΄λΌλ private μμ±μ κ°μ§κ³ μλλ°, μ΄λ μμ μ νλ‘ν νμ
μ΄ λλ λ€λ₯Έ κ°μ²΄λ₯Ό κ°λ¦¬ν¨λ€. μ΄λ κ² μμ μ νλ‘ν νμ
μ νλ‘ν νμ
μ νλ‘ν νμ
μ λ°λΌκ°λ€λ³΄λ©΄, κ²°κ΅ nullμ νλ‘ν νμ
μΌλ‘ κ°μ§λ μ€λΈμ νΈμμ λλλ€. nullμ νλ‘ν νμ
μ΄ λ μ΄μ μλ€κ³ μ μλλ©° μ΄λ νλ‘ν νμ
μ μ’
μ μ λ§νλ€.
var obj = {a: 'hello'}
console.dir(obj)
μμ± μμ
κ°μ²΄μ μ΄λ ν μμ±μ μ κ·Όνλ €κ³ ν λ, κ·Έ κ°μ²΄ μ체μ μμ± λΏλ§ μλλΌ κ°μ²΄μ νλ‘ν νμ , κ·Έ νλ‘ν νμ μ νλ‘ν νμ λ±λ±λ± μμ λ§ν νλ‘ν νμ μ μ’ λ¨ κΉμ§ κ° λκ°μ§ κ·Έ μμ±μ νμνλ€.
let foo = function () {
this.a = 1
this.b = 2
}
let bar = new foo() // {a:1, b:2}
foo.prototype.b = 3
foo.prototype.c = 4
// barκ° a μμ±μ κ°μ§κ³ μκΈ° λλ¬Έμ 1
console.log(bar.a)
// barκ° a μμ±μ κ°μ§κ³ μκΈ° λλ¬Έμ 2
console.log(bar.b)
// barκ° cμ μμ±μ κ°μ§κ³ μμ§ μλ€. κ·Έλμ νλ‘ν νμ
μ 체ν¬νλ€.
// foo.[[prototype]] μ΄ cλ₯Ό κ°κ³ μλμ§ νμΈνμ.
// cκ° μλ€.
// 4
console.log(bar.c)
// νλ‘ν νμ
μ λ€μ Έλ dλ λμ€μ§ μλλ€.
console.log(bar.d)
λ©μλ μμ
var foo = {
a: 2,
b: function (c) {
return this.a + 1
},
}
// 3
// μ¬κΈ°μ thisλ fooλ₯Ό κ°λ¦¬ν¨λ€
console.log(foo.b())
// barλ νλ‘ν νμ
μ fooλ‘ κ°μ§λ μ€λΈμ νΈλ€.
var bar = Object.create(foo)
bar.a = 4
// bar.b()λ₯Ό νΈμΆ νλ©΄, thisλ barλ₯Ό κ°λ¦¬ν¨λ€.
// λ°λΌμ fooμ ν¨μ bλ₯Ό μμ λ°μΌλ©°,
// aλ foo.aκ° μλ barμμ μλ‘μ§μ ν aλ₯Ό 보κ²λλ€.
// 5
console.log(bar.b())
How to use
function dummy() {}
console.dir(dummy.prototype)
μ¬κΈ°μ μμ±μ μΆκ°ν΄λ³΄μ.
function dummy() {}
dummy.prototype.foo = 'bar'
console.dir(dummy.prototype)
fooκ° bar
κ°μΌλ‘ μΆκ°λ κ²μ λ³Ό μ μλ€.
function dummy() {}
dummy.prototype.foo = 'bar'
var d = new dummy()
d.hello = 'world'
console.log(d)
- d μ μμ±μ μ κ·Όν λ, λΈλΌμ°μ λ μ°μ dκ° κ·Έ μμ±μ κ°μ§κ³ μλμ§ νμΈνλ€.
- λ§μ½ dκ° ν΄λΉ μμ±μ κ°μ§κ³ μμ§ μλ€λ©΄,
d.__proto__
(dummy.prototype
)μ΄ κ·Έ μμ±μ κ°μ§κ³ μλμ§ νμΈνλ€. - λ§μ½
dummy.__proto__
κ° κ·Έ μμ±μ κ°μ§κ³ μλ€λ©΄,dummy.__proto__
κ° κ°κ³ μλ μμ±μ μ¬μ©νλ€. - λ§μ½
dummy.__proto__
λ§μ κ·Έ μμ±μ κ°μ§κ³ μμ§ μμΌλ©΄,dummy.__proto__.__proto__
κ° κ°μ§κ³ μλμ§ νμΈνλ€. κΈ°λ³Έμ μΌλ‘ μ¬κΈ°μ ν¨μμ prototypeμ__proto__
λwindow.Object.prototype
μ΄λ€. - κ·Έλμ μ΄μ
dummy.__proto__.__proto__
(dummy.prototype
μ__proto__
) (Object.prototype
)μμ κ·Έ μμ±μ μ°Ύλλ€. - κ·Όλ° μ΄μ κ·Έ μμ
dummy.__proto__.__proto__.__proto__
λ₯Ό μ°ΎμΌλ €κ³ νμ§λ§, λ μ΄μμ μμΌλ―λ‘ - undefinedλ‘ κ²°λ‘ μ§λλ€.
μμ μ§λ ν κ³Όμ μ (....) μ½λλ‘ μ΄ν΄λ³΄μ.
function dummy() {}
dummy.prototype.foo = 'bar'
var d = new dummy()
d.prop = 'some value'
console.log('d.prop: ' + d.prop)
console.log('d.foo: ' + d.foo)
console.log('dummy.prop: ' + dummy.prop)
console.log('dummy.foo: ' + dummy.foo)
console.log('dummy.prototype.prop: ' + dummy.prototype.prop)
console.log('dummy.prototype.foo: ' + dummy.prototype.foo)
d.prop: some value
d.foo: bar
dummy.prop: undefined
dummy.foo: undefined
dummy.prototype.prop: undefined
dummy.prototype.foo: bar
μ¬λ¬κ°μ§ λ°©λ²μΌλ‘ κ°μ²΄λ₯Ό μμ±νκ³ νλ‘ν νμ μ²΄μΈ κ²°κ³Όλ₯Ό 보μ
λ¬Έλ² μμ±μ
var foo = {bar: 1}
// fooμ νλ‘ν νμ
μ Object.prototype
var arrayFoo = ['please', 'go', 'home']
// arrayFooμ νλ‘ν νμ
μ Array.prototype
// κ·Έλμ map, index λ±μ μΈ μ μλ€.
function functionFoo() {
return 'fuck'
}
// Function.prototypeμ μμλ°μμ
// call, bind λ±μΌλ₯΄ μΈ μ μλ€.
μμ±μλ₯Ό μ΄μ©
function hello() {
this.name = ''
this.age = 0
}
hello.prototype = {
setName: function (name) {
this.name = name
},
}
var h = new hello()
// hλ nameκ³Ό ageλ₯Ό μμ±μΌλ‘ κ°λ κ°μ²΄λ€.
// μμ±μ΄ h.[[prototype]]μ Hello.prototypeκ³Ό κ°μ κ°μ κ°μ§λ€.
Object.create νμ©
var a = {a: 1}
// a --> Object.prototype --> null
var b = Object.create(a)
// b --> a --> Object.prototype --> null
var c = Object.create(b)
// c --> b --> a --> Object.prototype --> null
[[prototype]] vs prototype
λͺ¨λ κ°μ²΄λ μμ μ νλ‘ν νμ
μ κ°λ¦¬ν€λ [[prototype]]
μ΄λΌλ μΈν°λ μ¬λ‘―μ κ°μ§λ©°, μμμ μν΄ μ¬μ©λλ€. ν¨μλ κ°μ²΄μ΄κΈ° λλ¬Έμ, [[prototype]]
λ₯Ό κ°λλ€. κ·Έλ°λ° ν¨μλ μΌλ° κ°μ²΄μλ λ¬λ¦¬ prototype
νλ‘ν νμ
λ κ°κ² λλ€. μ€μν κ²μ [[prototype]]
κ³Ό prototype
μ λ€λ₯΄λ€λ κ²μ΄λ€.
function Person(name) {
this.name = name
}
var foo = new Person('Lee')
console.dir(Person) // prototype νλ‘νΌν°κ° μλ€.
console.dir(foo) // prototype νλ‘νΌν°κ° μλ€.
function P(name) {
return name
}
var bar = P('Lee')
console.dir(bar)
[[prototype]]
- ν¨μλ₯Ό ν¬ν¨ν λͺ¨λ κ°μ²΄κ° κ°μ§κ³ μλ μΈν°λ μ¬λ‘―
- κ°μ²΄ μ
μ₯μμ λ΄€μλ, μμ μ λΆλͺ¨μν μ νλ νλ‘ν νμ
κ°μ²΄λ₯Ό κ°λ¦¬ν€λ©°, ν¨μμ κ²½μ°
Function.prototype
μ κ°λ¦¬ν¨λ€.
prototype νλ‘νΌν°
- μ€μ§ ν¨μλ§ κ°μ§κ³ μλ νλ‘νΌν°λ€.
- ν¨μ κ°μ²΄κ° μμ±μλ‘ μ΄μ©λ λ, μ΄ ν¨μλ₯Ό ν΅ν΄ μμ±λ κ°μ²΄μ λΆλͺ¨μν μ νλ κ°μ²΄λ₯Ό κ°λ¦¬ν¨λ€.
- μ μμ μμ
new Person('Lee')
λ μ΄ν¨μλ₯Ό ν΅ν΄foo
κ° λμλ€. μ΄foo
μ__proto__
λ₯Ό κ°λ¦¬ν¨λ€.
μ°¨μ΄λΉκ΅
function Person(name) {
this.name = name
}
var foo = new Person('Kim')
console.log(Person.__proto__ === Function.prototype)
console.log(Person.prototype === foo.__proto__)
Constructor
νλ‘ν νμ
κ°μ²΄λ constructor
νλ‘νΌν°λ₯Ό κ°λλ€. μ΄ constructor νλ‘νΌν°λ κ°μ²΄μ
μ₯μμ μμ μ μμ±ν κ°μ²΄λ₯Ό κ°λ¦¬ν¨λ€.
function Person(name) {
this.name = name
}
var foo = new Person('Lee')
// Person() μμ±μ ν¨μμ μν΄ μμ±λ κ°μ²΄λ₯Ό μμ±ν κ°μ²΄λ Person() μμ±μ ν¨μμ΄λ€.
console.log(Person.prototype.constructor === Person)
// foo κ°μ²΄λ₯Ό μμ±ν κ°μ²΄λ Person() μμ±μ ν¨μμ΄λ€.
console.log(foo.constructor === Person)
// Person() μμ±μ ν¨μλ₯Ό μμ±ν κ°μ²΄λ Function() μμ±μ ν¨μμ΄λ€.
console.log(Person.constructor === Function)
μ 리!!!
[[Prototype]]
μ μλ°μ€ν¬λ¦½νΈμ λͺ¨λ κ°μ²΄κ° κ°μ§ κ°μ΄λ©°,__proto__
λ‘ μ κ·Όν μ μλ€. (νΉμObject.getPrototypeOf(obj))
λ κ°λ₯νλ€. μ¬μ€ λκ°λ€.) μ΄κ²μ μ΄μ©ν΄ μμμ ꡬννλ©°, νκ³ νκ³ μ¬λΌκ°λ©΄Object.prototype
μ λ§λκ³Object.__proto__
λ nullμ΄λ€.prototype
μnew
λ‘ μλ‘μ΄ objectλ₯Ό λ§λ€μμλ (μμ±μλ‘ μ¬μ©λ λ), μ΄ ν¨μλ‘ μμ±λ κ°μ²΄μ λΆλͺ¨ μν μ ν κ°μ²΄λ₯Ό κ°λ¦¬ν¨λ€. (XXX.prototype
)XXX.prototype
κ°μ²΄λconstructor
λ₯Ό κ°λλ°,constructor
λ μμ μ μ μ₯μμ μμ μ μμ±ν κ°μ²΄λ₯Ό κ°λ¦¬ν¨λ€. λ°λΌμXXX
λ₯Ό κ°λ¦¬ν¨λ€.
Fooλ₯Ό μ€μ¬μΌλ‘ μ€λͺ ν΄λ³΄μ.
- Fooλ ν¨μλ€. λ°λΌμ μ΄ ν¨μμ νλ‘ν νμ
μ
Function.prototype
μ΄λ€. Foo
λ₯Ό μμ±μ ν¨μλ‘ μ¬μ©νμλ,prototype
νλ‘νΌν°λ₯Ό κ°κ²λλ©°,Foo.prototype
μ΄ μκΈ΄λ€.Foo.prototype
μ νλ‘ν νμ μObject
μ΄λ€. (ν¨μκ° μλ μλ‘μ΄ κ°μ²΄μ΄λ―λ‘Foo
λ₯Ό μμ±μν¨μλ‘,b
μc
λ₯Όnew
λ₯Ό μ΄μ©νμ¬ λ§λ€μλ€.b
μc
μ νλ‘ν νμ μFoo.prototype
μ΄λ€.
// μμ±μ ν¨μ
function Foo(y) {
// Objectλ₯Ό μμ±ν λ€μ, y νλ‘νΌν°μ yκ°μ κ°κ² λλ€.
this.y = y
}
// λν 'Foo.prototype'μ Fooμ prototypeμ ν λΉλλ©°,
// μ΄λ₯Ό νμ©ν΄μ νλ‘νΌν°λ λ©μλλ₯Ό μμλ°κ±°λ 곡μ ν μ μμΌλ©°,
// μμμ μ μν μμμ κ°μ΄ νμ©ν μ μλ€.
Foo.prototype.x = 10
// calculate λ©μλλ₯Ό μμλ°λλ€
Foo.prototype.calculate = function (z) {
return this.x + this.y + z
}
// Foo ν¨ν΄μ νμ©νμ¬ bμ c μ€λΈμ νΈλ₯Ό μμ±νλ€.
var b = new Foo(20)
var c = new Foo(30)
// μμλ°μ λ©μλλ₯Ό νΈμΆνλ€.
b.calculate(30) // 60
c.calculate(40) // 80
// νλ² νμΈν΄λ³΄μ.
console.log(
b.__proto__ === Foo.prototype, // true
c.__proto__ === Foo.prototype, // true
// Foo.prototypeμ constructorλΌλ μλ‘μ΄ νλ‘νΌν°λ₯Ό λ§λλλ°,
// μ΄λ ν¨μ κ·Έ μ체μ μμ±μλ₯Ό μ°Έμ‘°νκ² λλ€.
// b, c μμ±μλ Foo μ체μμ μ μ μλ€.
b.constructor === Foo, // true
c.constructor === Foo, // true
Foo.prototype.constructor === Foo, // true
b.calculate === b.__proto__.calculate, // true
b.__proto__.calculate === Foo.prototype.calculate, // true
)