new 키워드를 이용해 각종 정보를 담고 특정 기능을 수행하는 인스턴스를 만드는 기능입니다. 먼저 컨테이너 함수를 만들어야 합니다. 객체지향 언어의 클래스와 같은 역할입니다. 컨테이너 함수의 네이밍 컨벤션은 일반 함수와 달리 첫 글자가 대문자로 시작합니다.

function Student(){...}

이 함수는 다음과 같이 new 키워드로 생성하여 변수에 할당할 수 있습니다.

var kim = new Student()

이렇게 만든 새로운 Student 인스턴스는 변수에 따라 여러 개 생성할 수 있습니다.  lee, park 변수도 생성해봅시다.

var lee = new Student()
var park = new Student()

하지만 객체 안에 아무것도 없습니다. 매개 변수로 이름을 입력을 받도록 합니다.

function Student(name){
    this.name = name
}

var kim = new Student("김갑순")
var lee = new Student("이세모")
var park = new Student("박돌석")

여기서 this는 생성된 인스턴스를 가리킵니다. this.name = name은 입력받은 name을 인스턴스 객체의 name에 할당하라는 것입니다.

this 객체는 외부에서 접근할 수 있습니다. 위에서는 kim, lee, park 변수를 사용하여 접근할 수 있습니다. 이세모의 이름을 출력해 보겠습니다.

alert(lee.name) // 이세모

그런데 name을 바로 쓰거나 또는 var 에 할당하는 방법을 사용하지 않았을까요? this를 사용한 이유는 위의 예처럼 외부에서 접근 가능하도록 하기 위한 것이었습니다. 반대로 외부에서 접근할 수 없도록 하려면 값을 name을 바로 사용하거나 var 변수에 할당하면 됩니다.

function Student(inputName){
    var name = inputName
    console.warn(name + ": 인스턴스 내부에서만 사용 가능합니다. (private)")
}

var kim = new Student("김갑순")
...

console.log(kim)
...

이러한 private 변수들을 다른 메소드를 이용하여 접근 가능하게 하려면 setter/getter에 해당하는 메소드(함수)를 만들면 됩니다.

function Student(inputName){
    var name = inputName
    console.warn(name + ": 인스턴스 내부에서만 사용 가능합니다. (private)")
    
    this.setName = function(inputName){
        name = inputName
    }
    
    this.getName = function(){
        return name
    }
}

kim.setName("김면적")
console.log(kim.getName()) // 김면적

위에서 메소드라는 용어를 사용했는데 new를 사용해 만든 객체에 각종 함수를 할당하는 것도 가능합니다. 객체지향의 메소드와 용도는 사실상 동일합니다. 학생들의 국어, 영어, 수학 성적을 입력받아 합계와 평균을 내는 메소드를 작성해 보겠습니다.

function Student(inputName, kor, math, eng){
    this.name = inputName
    
    this.getSum = function(){
        return (kor + math + eng)
    }
    
    this.getAvg = function(){
        return this.getSum() / 3
    }
    
    this.toString = function(){
        return this.name + "의 성적 합계는 " + this.getSum().toFixed(2)
            + "점, 평균은 " + this.getAvg().toFixed(2) + "점 입니다."
    }
}

var kim = new Student("김갑순", 62, 35, 79)
var lee = new Student("이세모", 50, 38, 12)
var park = new Student("박돌석", 77, 16, 53)

console.log(kim.toString())
...

Prototype이란 것도 있습니다. 위에서 getSum, getAvg의 메소드는 인스턴스가 생성될 때마다 인스턴스 내에서 같이 생성됩니다. 만약 학생이 몇 천명이라고 한다면 똑같은 기능의 메소드가 인스턴스마다 들어있기 때문에 메모리가 낭비되게 됩니다. 이럴 때 공통되는 기능은 프로토타입으로 뺄 수 있습니다.

function Student(inputName, kor, math, eng) {
    this.name = inputName
    this.kor = kor
    this.math = math
    this.eng = eng


    this.message = this.name + "의 성적 합계는 " + this.getSum().toFixed(2) +
        "점, 평균은 " + this.getAvg().toFixed(2) + "점 입니다."
}
// Prototype
Student.prototype.getAvg = function() {
    return this.getSum() / 3
}

Student.prototype.getSum = function() {
    return (this.kor + this.math + this.eng)
}

var kim = new Student("김갑순", 62, 35, 79)
var lee = new Student("이세모", 50, 38, 12)
var park = new Student("박돌석", 77, 16, 53)

console.log(kim.message)
...

Student.prototype.getAvg 라는 이름을 통해 동일한 기능의 메소드를 밖으로 꺼낼 수 있습니다. 그 전 예제에서는 구현하려는 함수가 컨테이너 내부에 있어서 private 변수에 접근이 가능했지만 프로토타입을 통해 밖으로 꺼낸 경우 private 변수에는 접근할 수 없습니다. 따라서 this를 사용해야 합니다.

프로토타입 개념을 발전시켜 상속의 구현 등 복잡한 객체 지향 방식을 재현할 수도 있고, ES6 이후부터는 기존의 객체 지향 언어와 거의 동일한 문법으로 클래스 등을 작성할 수 있습니다. 프로토타입 개념은 내용이 방대하며 이해가 어렵기 때문에 더 알아보도록 하겠습니다.

프로토타입은 다른 객체에서도 응용할 수 있습니다. 예를 들어 배열의 컨테이너인 Array에 프로토타입을 적용해 내부의 합계를 구하는 커스텀 메소드를 작성하는 방법은 다음과 같습니다.

Array.prototype.getSum = function(){
    var sum = 0
    console.log(this)
    for(var i = 0; i < this.length; i++){
        sum += parseInt(this[i])
    }
    
    return sum
}

var score = [50, 75, 33]
console.log(score.getSum()) // 158

 

문의 | 코멘트 또는 yoonbumtae@gmail.com




1개의 댓글

자바스크립트: 객체지향 2 – 상속 구현 (ES5 이하) - BGSMM · 2019년 8월 22일 2:26 오전

[…] 이전 글: 자바스크립트: 객체지향 1 – new 키워드를 이용해 객체 생성 (ES5 이하) […]

답글 남기기

Avatar placeholder

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다