호쌤
호쌤 Just For Fun

[JS] Prototype

크리에이티브 커먼즈 라이선스 ITPAPER(호쌤,쭈쌤)에 의해 작성된 ≪[JS] Prototype≫은(는) 크리에이티브 커먼즈 저작자표시-비영리-동일조건변경허락 4.0 국제 라이선스에 따라 이용할 수 있습니다.
이 라이선스의 범위 이외의 이용허락을 얻기 위해서는 leekh4232@gmail.com으로 문의하십시오.

[JS] Prototype

객체지향 언어는 클래스 기반프로토타입 기반으로 구분되는데 자바스크립트는 이 중에서 프로토타입 기반에 속합니다. 프로토타입 기반이란 객체의 원형이 되는 형태를 먼저 정의해 놓고 추가적인 기능을 점차 확장하면서 기능을 구성하는 형식입니다.

#01. 생성자 함수

함수를 new 연산자로 호출할 경우 객체를 만들기 위한 함수로 분류된다.

이러한 함수를 생성자(Constructor)라고 한다.

생성자에서 this 예약어를 통해 정의한 변수는 객체의 멤버변수 역할을 한다.

단, 화살표 함수 형식은 생성자로 사용할 수 없다.

1) 생성자 정의하기

1
2
3
4
5
function User() {
    // 멤버변수 정의하기
    this._id = null;
    this._email = null;
};

2) 생성자를 통한 객체 생성

같은 생성자를 통해 할당된 객체는 동일한 자료 구조를 갖지만 각각 다른 정보를 저장할 수 있다.

1
2
3
4
5
6
7
8
9
var foo = new User();
foo._id = "hello";
foo._email = "hello@javascript.com";
console.log(foo);

var bar = new User();
bar._id = "world";
bar._email = "bar@javascript.com";
console.log(bar);
▶ 출력결과
1
2
User { _id: 'hello', _email: 'hello@javascript.com' }
User { _id: 'world', _email: 'bar@javascript.com' }

3) 파라미터를 갖는 생성자

객체에 포함되는 멤버변수의 초기값을 설정하기 위한 용도로 생성자 함수는 파라미터를 갖을 수 있다.

생성자 파라미터를 통해 객체 생성시 초기값을 한번에 설정하면, 객체를 생성한 후 개별적으로 파라미터를 지정하는 것 보다 전체 코드가 축약된다.

1
2
3
4
5
6
7
8
9
10
var User2 = function(id, email) {
    this._id = id;
    this._email = email;
};

var foo = new User2("hello", "hello@javascript.com");
var bar = new User2("world", "world@javascript.com");

console.log(foo);
console.log(bar);
▶ 출력결과
1
2
User2 { _id: 'hello', _email: 'hello@javascript.com' }
User2 { _id: 'world', _email: 'world@javascript.com' }

#02. 메서드 추가하기

JS의 모든 Object는 prototype이라는 속성을 갖는다.

이 속성을 생성자 함수에 대해 활용하면 생성자 함수에 속한 다른 변수나 함수를 추가할 수 있으며, 이 때 필요하다면 파라미터나 리턴값을 사용할 수 있다.

1
2
3
4
5
6
7
8
9
10
11
User2.prototype.login = function() {
    console.log("로그인되었습니다 -> id=%s, email=%s", this._id, this._email);
};

User2.prototype.logout = function() {
    console.log("로그아웃되었습니다");
};

var student = new User2("학생", "student@gmail.com");
student.login();
student.logout();
▶ 출력결과
1
2
로그인되었습니다 -> id=학생, email=student@gmail.com
로그아웃되었습니다

3) 객체의 기능 확장

User2 클래스 타입의 foo라는 이름의 객체가 생성된 후에 login(), logout() 두 개의 함수가 확장되었다. 이렇게 확장된 모든 함수들은 함수가 추가되기 전에 생성된 foo객체에도 바로 적용된다.

1
foo.login();
▶ 출력결과
1
로그인되었습니다 -> id=hello, email=hello@javascript.com

#03. getter, setter 추가하기

Object.defineProperty(생성자이름, 멤버변수이름, {getter,setter 정의}) 형식으로 특정 멤버변수에 대한 getter, setter를 정의할 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Object.defineProperty(User2.prototype, "id", {
    get: function() {
        return this._id;
    },
    set: function(value) {
        this._id = value;
    }
});

Object.defineProperty(User2.prototype, "email", {
    get: function() {
        return this._email;
    },
    set: function(value) {
        this._email = value;
    }
});

foo.id = "world";
foo.email = "world@javascript.com";
console.log(foo.id);
console.log(foo.email);
foo.login();
▶ 출력결과
1
2
3
world
world@javascript.com
로그인되었습니다 -> id=hello, email=hello@javascript.com

#04. JSON 구문 형식을 활용한 Prototype 정의

생성자이름.prototype = { ... } 형식으로 getter, setter, 함수 등을 한번에 추가할 수 있다.

이러한 형식으로 생성자, 멤버변수, getter, setter, 메서드 등이 묶여 있는 단위를 클래스라 한다.

1) 클래스 정의하기

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
39
40
41
// 생성자와 멤버변수 정의
function Member(username, password) {
    this._username = username;
    this._password = password;
}

Member.prototype = {
    // 멤버변수 _username에 대한 getter 정의
    get username() {
        return this._username;
    },

    // 멤버변수 _username에 대한 setter 정의
    set username(value) {
        this._username = value;
    },

    // 멤버변수 _password에 대한 getter 정의
    get password() {
        return this._password;
    },

    // 멤버변수 _password에 대한 setter 정의
    set password(value) {
        this._password = value;
    },

    // 로그인 메서드
    login: function() {
        console.log("[Member] 로그인되었습니다. username=%s, password=%s",
                    this.username, this.password);
    },

    // 로그아웃 메서드
    logout: function() {
        this.username = "";
        this.password = "";
        console.log("[Member] 로그아웃 되었습니다.. username=%s, password=%s",
                    this.username, this.password);
    },
};
▶ 출력결과
1
2
3
4
5
6
{
  username: [Getter/Setter],
  password: [Getter/Setter],
  login: [Function: login],
  logout: [Function: logout]
}

2) 클래스를 통한 객체 생성

클래스를 통해 객체를 생성하게 되면 객체는 클래스 안에 정의되어 있는 모든 기능을 부여 받는 특수한 형태의 변수로서 동작한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 생성자를 통한 객체 생성
var member1 = new Member("hello", "1234");

// setter를 통한 멤버변수 반환받기
console.log(member1.username);
console.log(member1.password);

// 메서드 호출
member1.login();
member1.logout();

// getter를 통한 멤버변수 값 변경
member1.username = "world";
member1.password = "5678";

// setter를 통한 멤버변수 반환받기
console.log(member1.username);
console.log(member1.password);

// 메서드 호출
member1.login();
▶ 출력결과
1
2
3
4
5
6
7
hello
1234
[Member] 로그인되었습니다. username=hello, password=1234
[Member] 로그아웃 되었습니다.. username=, password=
world
5678
[Member] 로그인되었습니다. username=world, password=5678

#05. Prototype을 통한 기능의 확장

Prototype은 기존에 존재하는 모든 형태의 클래스에 대한 기능 확장이 가능하다.

Javascript 안에 내장되어 있는 String 클래스 원형에 내가 원하는 기능을 추가하여 나만의 자바스크립트를 구성할 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 문자열에서 주어진 길이만큼 내용을 자르고 "..."을 추가
String.prototype.elipsis = function(length) {
    var value = this;   // this는 문자열 자체

    // 문자열의 길이가 length보다 크다면?
    if (value.length > length) {
        // 문자열의 0번째 위치부터 length까지 자름
        value = value.substring(0, length).trim();
        // 잘라낸 문자열에 "..." 덧붙임.
        value += "...";
    }

    // 결과 리턴
    return value;
}

var msg = "안녕하세요. 자바스크립트 프로그래밍 입니다.";
console.log(msg.elipsis(20));
▶ 출력결과
1
안녕하세요. 자바스크립트 프로그래밍...

크리에이티브 커먼즈 라이선스 ITPAPER(호쌤,쭈쌤)에 의해 작성된 ≪[JS] Prototype≫은(는) 크리에이티브 커먼즈 저작자표시-비영리-동일조건변경허락 4.0 국제 라이선스에 따라 이용할 수 있습니다.
이 라이선스의 범위 이외의 이용허락을 얻기 위해서는 leekh4232@gmail.com으로 문의하십시오.

comments powered by Disqus