본문으둜 κ±΄λ„ˆλ›°κΈ°

6. 객체지ν–₯ ν”„λ‘œκ·Έλž˜λ°

이 글은 κ³ ν˜„μ€€, μ†‘ν˜•μ£Ό λ‹˜μ˜ μΈμ‚¬μ΄λ“œ μžλ°”μŠ€ν¬λ¦½νŠΈλ₯Όμ°Έμ‘°ν•˜μ—¬ μž‘μ„±ν•œ κΈ€μž…λ‹ˆλ‹€.

클래슀 기반 μ–Έμ–΄ vs ν”„λ‘œν† νƒ€μž… 기반 μ–Έμ–΄#

λ¨Όμ € ν΄λž˜μŠ€λž€ 같은 μ’…λ₯˜μ˜ 집단에 μ†ν•˜λŠ” 속성(attribute)κ³Ό ν–‰μœ„(behavior)λ₯Ό μ •μ˜ν•œ κ²ƒμœΌλ‘œ, 객체지ν–₯ ν”„λ‘œκ·Έλž¨μ˜ 기본적인 μ‚¬μš©μž μ •μ˜ λ°μ΄ν„°ν˜•μ΄λΌκ³  ν•  수 μžˆλ‹€. κ²°κ΅­ ν΄λž˜μŠ€λŠ” 객체 생성에 μ‚¬μš©λ˜λŠ” νŒ¨ν„΄ ν˜Ήμ€ 청사진일 뿐이며 new μ—°μ‚°μžλ₯Ό ν†΅ν•œμΈμŠ€ν„΄μŠ€ν™” 과정이 ν•„μš”ν•˜λ‹€.

μ΄λŸ¬ν•œ 클래슀 기반 μ–Έμ–΄λŠ” λͺ¨λ“  μΈμŠ€ν„΄μŠ€κ°€ ν΄λž˜μŠ€μ— μ •μ˜λœ λŒ€λ‘œ 같은 ꡬ쑰이고, 보톡 λŸ°νƒ€μž„μ— κ·Έ ꡬ쑰λ₯Ό λ³€κ²½ν•  수 μ—†λ‹€. μ΄λŸ¬ν•œ νŠΉμ„±μ€ μ •ν™•μ„±, μ•ˆμ •μ„±, μ˜ˆμΈ‘μ„± μΈ‘λ©΄μ—μ„œ μ’‹μ§€λ§Œ, ν”„λ‘œν† νƒ€μž… 기반의 μ–Έμ–΄λŠ” λ™μ μœΌλ‘œ 자유둭게 객체의 ꡬ쑰와 λ™μž‘ 방식을 λ°”κΏ€ 수 μžˆλ‹€λŠ” μž₯점이 μžˆλ‹€.

μžλ°”μŠ€ν¬λ¦½νŠΈλŠ” 클래슀 κ°œλ…μ΄ μ—†κ³  λ³„λ„μ˜ 객체 생성 방식이 μ‘΄μž¬ν•œλ‹€.

  • 객체 λ¦¬ν„°λŸ΄

  • Object() μƒμ„±μž ν•¨μˆ˜

  • μƒμ„±μž ν•¨μˆ˜

μžλ°”μŠ€ν¬λ¦½νŠΈλŠ” 거의 λͺ¨λ“  것이 객체이고, ν•¨μˆ˜ 객체둜 λ§Žμ€ 것을 κ΅¬ν˜„ν•΄λ‚΄λŠ”λ°, 클래슀, μƒμ„±μž, λ©”μ†Œλ“œλ„ λͺ¨λ‘ ν•¨μˆ˜λ‘œ κ΅¬ν˜„μ΄ κ°€λŠ₯ν•˜λ‹€.


function Person(name) {    this.name = name;
    this.getName = function () {        return this.name;    };
    this.setName = function (value) {        this.name = value;    };}
var me = new Person('zzoon');console.log(me.getName()); // zzoon
me.setName('iamhjoo');console.log(me.getName()); // iamhjoo

μ—¬κΈ°μ„œ new ν‚€μ›Œλ“œλ‘œ μƒˆλ‘œμš΄ 객체 me λ₯Ό λ§Œλ“  뢀뢄을 μ£Όλͺ©ν•˜μž.


var me = new Person('zzoon');

이 ν˜•νƒœλŠ” κΈ°μ‘΄ 객체지ν–₯ ν”„λ‘œκ·Έλž˜λ° μ–Έμ–΄μ—μ„œ ν•œ 클래슀의 μΈμŠ€ν„΄μŠ€λ₯Ό μƒμ„±ν•˜λŠ” μ½”λ“œμ™€ 맀우 μœ μ‚¬ν•˜λ‹€. ν•¨μˆ˜ Person 이 클래슀이자 μƒμ„±μžμ˜ 역할을 ν•˜λŠ” 것이닀.

μžλ°”μŠ€ν¬λ¦½νŠΈμ—μ„œ 클래슀 기반의 객체지ν–₯ ν”„λ‘œκ·Έλž˜λ°μ€ 기본적인 ν˜•νƒœκ°€ 이와 κ°™μ•„μ„œν΄λž˜μŠ€ 및 μƒμ„±μžμ˜ 역할을 ν•˜λŠ” ν•¨μˆ˜κ°€ 있고 μ‚¬μš©μžκ°€ new ν‚€μ›Œλ“œλ‘œ μΈμŠ€ν„΄μŠ€λ₯Ό μƒμ„±ν•˜μ—¬ μ‚¬μš©ν•  수 μžˆλ‹€.

ν•˜μ§€λ§Œ 이것은 λ¬Έμ œκ°€ λ§Žμ€ μ˜ˆμ œμ΄λ‹€. Person μƒμ„±μž ν•¨μˆ˜λ‘œ μ—¬λŸ¬ 객체λ₯Ό λ§Œλ“ λ‹€κ³ ν•΄λ³΄μž.


var me = new Person('me');var you = new Person('you');var him = new Person('him');

μ΄λ ‡κ²Œ μ‚¬μš©ν•˜λŠ” 것은 κ²‰μœΌλ‘œλŠ” 별 문제 없이 μž‘λ™ν•˜μ§€λ§Œ, 각 κ°μ²΄λŠ” 자기 μ˜μ—­μ—μ„œκ³΅ν†΅μ μœΌλ‘œ μ‚¬μš©ν•  수 μžˆλŠ” setName() , getName() ν•¨μˆ˜λ₯Ό λ”°λ‘œ μƒμ„±ν•˜κ³  μžˆμ–΄μ„œ, μ€‘λ³΅λ˜λŠ” μ˜μ—­μ„ λΆˆν•„μš”ν•˜κ²Œ λ©”λͺ¨λ¦¬μ— μ˜¬λ €λ†“κ³  μ‚¬μš©ν•˜κ³  μžˆλ‹€.

μ΄λŸ¬ν•œ 문제λ₯Ό ν•΄κ²°ν•˜λŠ” 방법은 μžλ°”μŠ€ν¬λ¦½νŠΈμ˜ ν”„λ‘œν† νƒ€μž… 기반의 객체지ν–₯을 μ΄μš©ν•˜λŠ” 것이닀.


function Person(arg) {    this.name = arg;}
Person.prototype.getName = function () {    return this.name;};
Person.prototype.setName = function (value) {    this.name = value;};
var me = new Person('me');var you = new Person('you');console.log(me.getName());console.log(you.getName());

이 μ˜ˆμ œμ—μ„œλŠ” Person ν•¨μˆ˜ 객체의 prototype ν”„λ‘œνΌν‹°μ— getName() κ³Ό setName() ν•¨μˆ˜λ₯Ό μ •μ˜ν–ˆλ‹€. 이 Person 으둜 객체λ₯Ό μƒμ„±ν•œλ‹€λ©΄, 각 κ°μ²΄λŠ” κ°μžλ”°λ‘œ ν•¨μˆ˜ 객체λ₯Ό 생성할 ν•„μš” 없이 getName() κ³Ό setName() ν•¨μˆ˜λ₯Ό ν”„λ‘œν† νƒ€μž…μ²΄μΈμœΌλ‘œ μ ‘κ·Όν•  수 μžˆλ‹€.


2020-03-09-6-객체지ν–₯-ν”„λ‘œκ·Έλž˜λ°-image-0

μ΄λ ‡κ²Œ μžλ°”μŠ€ν¬λ¦½νŠΈμ—μ„œ 클래슀 μ•ˆμ˜ λ©”μ†Œλ“œλ₯Ό μ •μ˜ν•  λ•ŒλŠ” ν”„λ‘œν† νƒ€μž… 객체에 μ •μ˜ν•œ ν›„, new 둜 μƒμ„±ν•œ κ°μ²΄μ—μ„œ μ ‘κ·Όν•  수 있게 ν•˜λŠ” 것이 μ’‹λ‹€.


μ•„λž˜λŠ” λ”κΈ€λΌμŠ€ ν¬λ½ν¬λ“œκ°€ μ œμ•ˆν•œ ν”„λ‘œν† νƒ€μž… 객체에 λ©”μ†Œλ“œλ₯Ό μΆ”κ°€ν•˜λŠ” 방식이닀.


Function.prototype.method = function (name, func) {    if (!this.prototype[name]) {        this.prototype[name] = func;    }};
function Person(arg) {    this.name = arg;}
Person.method('setName', function (value) {    this.name = value;});
Person.method('getName', function () {    return this.name;});
var me = new Person('me');var you = new Person('you');
console.log(me.getName()); // meconsole.log(you.getName()); // you

상속#

μžλ°”μŠ€ν¬λ¦½νŠΈλŠ” 클래슀λ₯Ό 기반으둜 ν•˜λŠ” 전톡적인 상속을 μ§€μ›ν•˜μ§€λŠ” μ•Šμ§€λ§Œ, 객체 ν”„λ‘œν† νƒ€μž… 체인을 μ΄μš©ν•˜μ—¬ 상속을 κ΅¬ν˜„ν•΄λ‚Ό 수 μžˆλ‹€. μ΄λŸ¬ν•œ μƒμ†μ˜ κ΅¬ν˜„ 방식은 ν¬κ²Œλ‘ κ°€μ§€λ‘œ ꡬ뢄할 수 μžˆλŠ”λ°, ν•˜λ‚˜λŠ” 클래슀 기반 μ–Έμ–΄μ˜ 상속 방식을 ν‰λ‚΄λ‚΄λŠ” 것(μ˜μ‚¬ 클래슀 νŒ¨ν„΄ 상속, Pseudo-classical Inheritance)이고, 두 λ²ˆμ§ΈλŠ” ν”„λ‘œν† νƒ€μž…μœΌλ‘œμƒμ†μ„ κ΅¬ν˜„ν•˜λŠ” 것(ν”„λ‘œν† νƒ€μž… νŒ¨ν„΄ 상속, Prototypal Inheritance)이닀.


μ˜μ‚¬ 클래슀 νŒ¨ν„΄ 상속#

μ˜μ‚¬ 클래슀 νŒ¨ν„΄μ€ μžμ‹ μƒμ„±μž ν•¨μˆ˜μ˜ prototype ν”„λ‘œνΌν‹°λ₯Ό λΆ€λͺ¨ μƒμ„±μž ν•¨μˆ˜μ˜μΈμŠ€ν„΄μŠ€λ‘œ κ΅μ²΄ν•˜μ—¬ 상속을 κ΅¬ν˜„ν•˜λŠ” 방법이닀.


function Person(arg) {    this.name = arg;}
Person.prototype.setName = function (value) {    this.name = value;};
Person.prototype.getName = function () {    return this.name;};
function Student(arg) {}
var you = new Person('iamhjoo');Student.prototype = you;
var me = new Student('zzoon');me.setName('zzoon');console.log(me.getName());

μ΄λŸ¬ν•œ 방식은 λͺ‡ 가지 문제λ₯Ό κ°–κ³  μžˆλ‹€.

  • me μΈμŠ€ν„΄μŠ€λ₯Ό 생성할 λ•Œ λΆ€λͺ¨ 클래슀인 Person 의 μƒμ„±μžλ₯Ό ν˜ΈμΆœν•˜μ§€ μ•ŠλŠ”λ‹€.

이 μ½”λ“œλ‘œ me μΈμŠ€ν„΄μŠ€λ₯Ό 생성할 λ•Œ 'zzoon' 을 λ„˜κ²ΌμœΌλ‚˜ 이λ₯Ό λ°˜μ˜ν•˜λŠ” μ½”λ“œκ°€μ—†μ–΄μ„œ setName() λ©”μ†Œλ“œκ°€ 호좜되고 λ‚˜μ„œμ•Ό me 객체에 name ν”„λ‘œνΌν‹°κ°€ λ§Œλ“€μ–΄μ§„λ‹€.

이λ₯Ό ν•΄κ²°ν•˜κΈ° μœ„ν•΄ Student ν•¨μˆ˜μ— λ‹€μŒ μ½”λ“œλ₯Ό μΆ”κ°€ν•˜μ—¬ λΆ€λͺ¨ 클래슀의 μƒμ„±μžλ₯Όν˜ΈμΆœν•΄μ•Ό ν•œλ‹€.


function Student(arg) {    Person.apply(this, arguments);}

Student ν•¨μˆ˜ μ•ˆμ—μ„œ μƒˆλ‘­κ²Œ μƒμ„±λœ 객체λ₯Ό apply ν•¨μˆ˜μ˜ 첫 번째 인자둜 λ„˜κ²¨ Person ν•¨μˆ˜λ₯Ό μ‹€ν–‰μ‹œν‚¨λ‹€.

  • new μ—°μ‚°μžλ₯Ό 톡해 μΈμŠ€ν„΄μŠ€λ₯Ό μƒμ„±ν•œλ‹€.

μƒμ„±μž ν•¨μˆ˜ μ‚¬μš©μ—λŠ” μœ„ν—˜μ΄ μ‘΄μž¬ν•˜λŠ”λ° λ§Œμ•½ μƒμ„±μž ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•  λ•Œ new μ—°μ‚°μžλ₯Ό ν¬ν•¨ν•˜λŠ” 것을 잊게 되면, this κ°€ μƒˆλ‘œμš΄ 객체와 λ°”μΈλ”©λ˜μ§€ μ•Šκ³  μ „μ—­ κ°μ²΄μ—λ°”μΈλ”©λœλ‹€.

  • μƒμ„±μž 링크의 파괴

μœ„ μ˜ˆμ œμ—μ„œ Student 객체의 ν”„λ‘œν† νƒ€μž…μ€ Person μƒμ„±μž ν•¨μˆ˜κ°€ μƒμ„±ν•œ you 객체이닀. ν”„λ‘œν† νƒ€μž… κ°μ²΄λŠ” λ‚΄λΆ€ ν”„λ‘œνΌν‹°λ‘œ constructor λ₯Ό 가지며, μ΄λŠ” μƒμ„±μžν•¨μˆ˜λ₯Ό κ°€λ¦¬ν‚€λŠ” 반면 you κ°μ²΄λŠ” constructor ν”„λ‘œνΌν‹°λ₯Ό 가지고 μžˆμ§€ μ•Šκ³ , λ”°λΌμ„œ ν”„λ‘œν† νƒ€μž… 체인에 μ˜ν•΄ Person.prototype 의 constructor 인 Person ν•¨μˆ˜λ₯Όκ°€λ¦¬ν‚€κ²Œ λœλ‹€.

  • κ°μ²΄λ¦¬ν„°λŸ΄

μ˜μ‚¬ 클래슀 νŒ¨ν„΄ 상속은 기본적으둜 μƒμ„±μž ν•¨μˆ˜λ₯Ό μ΄μš©ν•˜κΈ° λ•Œλ¬Έμ— κ°μ²΄λ¦¬ν„°λŸ΄ νŒ¨ν„΄μœΌλ‘œ μƒμ„±ν•œ 객체의 μƒμ†μ—λŠ” μ ν•©ν•˜μ§€ μ•Šλ‹€. μ΄λŠ” κ°μ²΄λ¦¬ν„°λŸ΄ νŒ¨ν„΄μœΌλ‘œ μƒμ„±ν•œ 객체의 μƒμ„±μž ν•¨μˆ˜λŠ” Object() 이고 이λ₯Ό λ³€κ²½ν•  방법이 μ—†κΈ° λ•Œλ¬Έμ΄λ‹€.

ν”„λ‘œν† νƒ€μž…μ„ μ΄μš©ν•œ 상속#

ν”„λ‘œν† νƒ€μž… νŒ¨ν„΄ 상속은 Object.create ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•˜μ—¬ κ°μ²΄μ—μ„œ λ‹€λ₯Έ 객체둜 직접상속을 κ΅¬ν˜„ν•˜λŠ” 방식이닀. ν”„λ‘œν† νƒ€μž… νŒ¨ν„΄ 상속은 κ°œλ…μ μœΌλ‘œ μ˜μ‚¬ 클래슀 νŒ¨ν„΄ 상속보닀 κ°„λ‹¨ν•˜λ©°, μ˜μ‚¬ 클래슀 νŒ¨ν„΄μ˜ 단점인 new μ—°μ‚°μžκ°€ ν•„μš”μ—†κ³  μƒμ„±μž λ§ν¬λ„νŒŒκ΄΄λ˜μ§€ μ•ŠμœΌλ©° 객체 λ¦¬ν„°λŸ΄μ—λ„ μ‚¬μš©ν•  수 μžˆλ‹€.