[JavaScript] 객체지향 프로그래밍

Constructor, Method

더글라스 크락포드가 제시한 함수 메소드 정의 방법이다
Function의 prototype으로 메소드를 정의할 수 있도록 하여 메모리 릭이 생기는것을 방지한다
프로토타입으로 생성된 클래스의 메소드는 해당 클래스영역 내에서 모두 공유한다

1
2
3
4
Function.prototype.method = function(name, func) {
if(!this.prototype[name])
this.prototype[name] = func;
}

이를 기반으로 다음과 같이 생성자를 만들 수 있다

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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");
console.log(me.getName());

상속

프로토타입 상속

Object.create()를 풀면 다음과 같이 동작한다
인자로 들어온 오브젝트를 부모로 하는 자식객체를 생성하여 리턴한다

1
2
3
4
5
function Object_create(obj) {
function F() {}
F.prototype = obj;
return new F();
}

또한 자식 객체는 부모 객체의 메소드를 오버라이드 할 수 있어야한다

1
2
3
4
5
function extend(obj, prop) {
if( !prop ) { prop = obj; obj = this; }
for (var i in prop) obj[i] = prop[i];
return obj;
};

위와 같은 코드에서 메소드를 재정의하고 있다
!prop의 경우는 인자가 하나만 들어오는 경우이다

클래스 기반 상속

클래스 기반 상속은 다음과 같이 이루어진다
부모와 자식 사이에 빈 인스턴스를 두고 이 빈 인스턴스가 부모와 자식을 연결한다
빈 인스턴스는 클로저로써 가비지컬렉터의 대상이 아니게된다

1
2
3
4
5
6
7
8
9
var inherit = function(Parent, Child) {
var F = function() {};
return function(Parent, Child) {
F.prototype = Parent.prototype;
Child.prototype = new F();
Child.prototype.constructor = Child;
Child.super = Parent.prototype;
};
}();

캡슐화

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var Person = function(arg) {
var name = arg ? arg : undefined;

var Func = function() {};
Func.prototype = {
getName: function() {
return name;
},
setName: function(arg) {
name = arg;
}
};

return Func;
}();

위의 코드에서 Func 객체를 리턴함으로써 Person객체의 프로토타입에 접근할 수 있게 된다
또한 클로저를 사용해 name에는 접근할 수 없게된다
하지만 주의해야할 사항에서는 반환하는 객체의 private 멤버가 객체와 같이 참조값을 가지는 멤버라면 깊은 복사를 해주어야한다

클래스

위의 내용을 종합한 클래스의 코드는 다음과 같다

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
var subClass = function() {
//F를 클로저로 사용한다
var F = function () {
};

function SubClass(obj) {
//최상위 클래스를 Function을 상속받도록 한다
var parent = this === window ? Function : this;

var child = function () {
var _parent = child.parent;

if (_parent && _parent !== Function) {
_parent.apply(this, arguments);
}

if (child.prototype._init) {
child.prototype._init.apply(this, arguments);
}
};

//클래스 기반 상속
F.prototype = parent.prototype;
child.prototype = new F();
child.prototype.constructor = child;
child.parent = parent;
child.subClass = arguments.callee;

//자신만의 프로퍼티를 복사한다
for (var i in obj) {
if (obj.hasOwnProperty(i)) {
child.prototype[i] = obj[i];
}
}

return child();
}
}();
Author: Song Hayoung
Link: https://songhayoung.github.io/2020/07/17/Languages/JS/oop/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.