JavaScript

[JavaScript] Class(클래스), private(접근제어)

SangRok Jung 2022. 4. 20. 22:40
반응형

Class (클래스)

개념

ES5에서는 클래스가 없으며 객체형, 클로저, 생성자, 프로토타입 등을 이용해 클래스와 유사한 구조를 만들어 사용한다.

ES5와 다르게 ES6에서는 클래스 문법을 직접적으로 지원함.

내부적으로 Class는 격국 object형과 같다.

 

형식

<body>
    <script>
        class class_name {}
        new class_name
    </script>
</body>

 

선언과 인스턴스 생성

<body>
    <script>
        class CS 
        {

        }


        const a = new CS();
        const aArray = [new CS(), new CS(), new CS()];

    </script>
</body>

 

클래스의 생성자

constructor로 생성자를 호출한다.

ES6때 출현.

class cs {
	constructor(){}
}

 

this를 통해 object에 변수를 등록한다. (object와 유사함.)

<body>
    <script>
        class student 
        {
            constructor(_id = 0, _name = 0, _score = 0) //default parameter
            {
                this.id = _id;
                this.name = _name;
                this.score = _score;
            }
        };

        const s1 = new student('JSR', '정상록', '100')
        console.log(s1.id)
        console.log(s1.name)
        console.log(s1.score)

        //JSR
        //정상록
        //100
    </script>
</body>

 

* 생성자에 객체를 추가할 시 Shallow Copy(얕은 복사)에 주의한다.

<body>
    <script>
        class student 
        {
            constructor(_id = 0, _name = 0, _score = 0)
            {
                this.id = _id;
                this.name = _name;
                this.score = _score;
            }
        };

        const score = [100, 35, 88, 85]
        const s1 = new student('JSR', '정상록', score);
        
        console.log(s1.score);

        score[0] = 50;

        console.log(s1.score)

        //(4) [100, 35, 88, 85]
        //(4) [50, 35, 88, 85]
    </script>
</body>

Shallow Copy

 

* Shallow copy(얕은 복사) 해결. (private 하단 참조)

<body>
    <script>
        class student 
        {   
            #id
            #name
            #score
            constructor(_id = 0, _name = 0, _score = 0)
            {
                this.#id = _id;
                this.#name = _name;
                this.#score = [..._score];
                
            }
            getScore(){
                return this.#score
            }
        };

        const score = [100, 35, 88, 85]
        const s1 = new student('JSR', '정상록',score);

        console.log(s1.getScore());

        //(4) [100, 35, 88, 85]
    </script>
</body>

Deep Copy

 

 

 

 

 

Method 추가

class의 method로 추가

  • readability(가독성)이 좋다.
  • 가장 기본적인 방법이다.
<body>
    <script>
        class student 
        {
            constructor(_id = 0, _name = 0, _score = 0)
            {
                this.id = _id;
                this.name = _name;
                this.score = _score;
            }

                getId = function()
                {
                    return this.id
                }
            
        };

        const s1 = new student('220000', 'JSR', '정상록')
        console.log(s1.getId())

        //220000

    </script>
</body>

 

Prototype을 사용한 Method 추가

  • readability(가독성)이 떨어지는 치명적인 문제가 있다.
<body>
    <script>
        class student 
        {
            constructor(_id = 0, _name = 0, _score = 0)
            {
                this.id = _id;
                this.name = _name;
                this.score = _score;

            }


            
        };

        student.prototype.getId = function()
        {
            return this.id
        }

        const s1 = new student('220000', 'JSR', '정상록')

        console.log(s1.getId())
        //220000

    </script>
</body>

 

인스턴스로 추가.

  • readability(가독성)이 떨어지는 치명적인 문제가 있다.
<body>
    <script>
        class student 
        {
            constructor(_id = 0, _name = 0, _score = 0)
            {
                this.id = _id;
                this.name = _name;
                this.score = _score;

            }


            
        };

        student.prototype.getId = function()
        {
            return this.id
        }

        const s1 = new student('220000', 'JSR', '정상록')

        s1.func = function()
        {
            console.log("Instance로 추가.")
        }

    </script>
</body>

 

 

 

 


 

 

 

문제

 

id, name, 3개의 score와 평균을 구하는 메서드를 가진 student 클래스를 구현하고자 한다.

각각의 장단점과 결론을 설명하시오.

  1. Object를 이용하여 구현하시오.
  2. constructor + prototype로 구현하시오.
  3. closure로 구현하시오.
  4. class로 구현하시오.

 

1. Object를 이용하여 구현하시오.

 

https://cruella-de-vil.tistory.com/38

 

[JavaScript] object type(객체형) +예제

객체형(Object type) 필요한 데이터와 기능을 가지고 있다. ▶ 개념 Primitive type을 제외한 데이터 타입의 베이스 인스턴스. JavaScript의 거의 모든 객체는 Object의 파생 인스턴스다. 데이터를 읽고 쓰는

cruella-de-vil.tistory.com

<body>
    <script>
        //object를 이용하여 만들기

        const student1 = {
            getAv : function() {
                let av = 0;
                for (let val of this.score)
                {
                    av = av + val;
                }
                return (av/this.score.length).toFixed(2); 
            }
        };

        const student2 = {
            id : 'JO',
            name : '조온',
            score : [80, 70, 98],
            getAv : function() {
                let av = 0;
                for (let val of this.score)
                {
                    av = av + val;
                }
                return (av/this.score.length); 
            }
        };

        const score = [100, 90, 80]
        student1.id = 'JSR'
        student1.name = '정상록'
        student1.score = score
        
        //출력
        console.log(student1.id)
        console.log(student1.name)
        console.log(student1.score)
        console.log(student1.getAv().toFixed(2))

        //JSR
        //정상록
        //(3) [100, 90, 80]
        //90.00
    </script>
</body>

장점 : 

  1. 직관적이다.
  2. 코딩하기 쉽다.
  3. Shallow copy와 상관없이 독립적으로 데이터를 유지한다.

단점 : 

  1. 인스턴스 추가시 추가적인 코드가 발생한다.
  2. 코드의 중복이 일어난다.
  3. 코드의 일관성이 없어질 수 있는 여지가 존재한다.
  4. 접근제어 기능이 부재하다.

결론 :

  1. 인스턴스가 3개 이상이 되는 경우 object 방식은 좋지 않다.
  2. 함수의 수가 다수 존재할수록 복잡해진다.
  3. 정보가 단순할 경우 사용한다.
  4. Singleton 패턴에서 사용한다.

 

 

2.  Constructor + Prototype을 이용하여 구현하시오.

 

https://cruella-de-vil.tistory.com/52

 

[JavaScript] 객체지향, Constructor(생성자), new

객체지향 자바스크립트 데이터, 함수 기반 프로그래밍 data가 보호받지 못하는 문제점이 있다. func2 입장에서 data1이 바뀐 이유에 대해서 알 수 없다. 객체지향 프로그래밍 기존의 데이터, 함수 기

cruella-de-vil.tistory.com

https://cruella-de-vil.tistory.com/54

 

[JavaScript] Prototype

Prototype 개념 prototype의 사전적 의미는 “원형"이다. 즉 “원래의 모양”을 뜻한다. 자바스크립트에서 사용하는 거의 모든 데이터는 기본적으로 “객체“(Object type)이다. 객체는 객체마다 기

cruella-de-vil.tistory.com

<body>
    <script>
        const student = function(_id, _name, _score)
        {
            this.id = _id;
            this.name = _name;
            this.score = [..._score] //spread
            
            this.getTotal = function()
            {
                let total = 0;
                for (let val of this.score)
                {
                    total = total + val;
                }
                return total;
            }
        }

        //prototype method 확장
        student.prototype.getAverage = function()
        {   
            let total = 0;
            for (let val of this.score)
            {
                total = total + val;
            }
            return (total/this.score.length);
        }

        
        const score = [100, 87, 54]

        const s1 = new student('JSR', '정상록', score)
        const s2 = new student('JJ', '조조', [90, 70, 88])

    
        //출력
        console.log(s1.score)
        console.log(s1.name)
        console.log(s1.id)
        console.log(s1.getAverage().toFixed(2))

        //(3) [100, 87, 54]
        //정상록
        //JSR
        //80.33
    </script>
</body>

장점 : 

  1. 객체의 생성부와 정의부가 분리된다. (중복제거, 가독성 증가...)
  2. 코드의 중복이 없다.

단점 : 

  1. 메서드나 속성의 위치가 애매하다.
  2. this가 맥락에 따라 달라진다.
  3. 접근제어 기능이 부재하다. (No private) / 해결 : closure

결론 :

  1. 생성자로 사용할 시 method를 prototype으로 확장하지 않아도 된다.

 

 

 

 

3. closure로 구현하시오.

 

https://cruella-de-vil.tistory.com/53

 

[JavaScript] Closure(클로저) 예제

들어가기 앞서 Closure의 이해 https://cruella-de-vil.tistory.com/47 [JavaScript] Scope(스코프), Closure(클로저), var Scope (스코프) 개념 변수가 유효성을 가지는 범위. 스코프는 기본적으로 프로세스 메..

cruella-de-vil.tistory.com

<body>
    <script>
        //closure
        const makeStudent = function (_id, _name, _score)
        {   
            //Deep Copy 처리.
            //L Val = R Val(우선처리)
            _score = [..._score];
            //기능 구현의 일관성이 떨어진다.


            return {
                getId() {
                    return _id;
                },

                setId(id) {
                    _id = id;
                },

                getName() {
                    return _name;
                },

                setName(name) {
                    _name = name;
                },

                getScore() {
                    return _score;
                },

                setScore(score, idx) {
                    _score[idx] = score;
                },

                getAverage() {
                    let total = 0;
                    for (let val of _score)
                    {
                        total = total + val;
                    }
                    return (total/_score.length);
                }
            }
        }

        const score = [90, 87, 77];

        const st1 = makeStudent('JSR', '정상록',score)

        console.log(st1.getScore())
        console.log(st1.getId())
        console.log(st1.getAverage().toFixed(1))

        st1.setScore(100, 1)
        console.log(st1.getScore())
        console.log(st1.getAverage().toFixed(1))

        //(3) [90, 87, 77]
        //JSR
        //84.7
        //(3) [90, 100, 77]
        //89.0
    </script>
</body>

장점 : 

  1. 접근 제어가 가능하다.
  2. 객체의 선언부와 정의부가 분리된다.
  3. 코드의 중복이 없다.

단점 : 

  1. 문법적으로 어렵다. (내부 메커니즘 중 scope chain을 오용.)
  2. 기능 구현의 일관성이 없다.

결론 : ES5가 가지는 object, constructor, prototype, closure는 문제점과 한계가 존재한다.

 

 

 

4. Class를 이용하여 구현하시오.

<body>
    <script>
        //class를 이용하여 만들기
        class student 
        {
            constructor(_id = 0, _name = 0, _score = 0)
            {
                this.id = _id;
                this.name = _name;
                this.score = [..._score];
            }

            //id
            getId() {
                return this.id;
            }
            setId(_id) {
                this.id = _id;
            }

            //name
            getName() {
                return this.name;
            }
            setName(_name) {
                this.name = _name;
            }

            //score
            getScore() {
                return this.score;
            }
            setScore(score ,idx) {
                this.score[idx] = score
            }

            //평균
            getAverage() {
                let total = 0;
                for (let val of this.score)
                {
                    total = total + val;
                }
                return total/this.score.length;
            }
            
        };
        const score = [100, 87, 54]

        const st1 = new student('JSR', '정상록', score)


        //출력
        st1.setId('SSS');
        st1.setScore(0, 1);

        console.log(st1.getId())
        console.log(st1.getName())
        console.log(st1.getScore())
        console.log(st1.getAverage().toFixed(1))
        //SSS
        //정상록
        //(3) [100, 0, 54]
        //51.3
    </script>
</body>

장점 : 

  1. 접근제어가 용이하다.
  2. 객체의 선언부와 정의부가 분리된다.
  3. 다른 언어 객체지향 언어(ex) java)에서 사용하는 구현 스킬을 그대로 사용한다.
  4. 가독성이 좋다.

단점 : 

  1. 현재로서 단점은 해결이 불가능하다.

결론 : Class는 ES5의 단점을 개선시켰다.

 

 

 

 


 

 

접근제어

private

클래스의 속성이나 메서드를 외부에서 접근할 수 없도록 하는 한정자.

#을 붙여 전방선언 한 뒤 모든 속성에 #을 붙임

이는 변수 명자체가 변경됨을 의미한다. EX) id → #id

 

<body>
    <script>
        class cs {
        	//private 선언
            #a;
            #b;

            constructor(_a, _b) {
                this.#a = _a;
                this.#b = _b;
            }

            getA(){
                return this.#a
            }
            getB(){
                return this.#b
            }

            getAdd(){
                return this.#a + this.#b
            }
        }

        const result = new cs(10, 9)

        console.log(result.getA())
        console.log(result.getB())
        console.log(result.getAdd())

        //10
        //9
        //19
    </script>
</body>

 

 

 

get, set

getter, setter를 위해서 만든 새로운 문법

형식

<body>
    <script>
        class cs {
            #a;
            #b;

            constructor(_a, _b) {
                this.#a = _a;
                this.#b = _b;
            }

            get attribute_name () {
                return value;
            }

            set attribute_name (value) {

            }
        }
    </script>
</body>

 

 

 

예시

<body>
    <script>
        class cs {
            #a;
            #b;

            constructor(_a, _b) {
                this.#a = _a;
                this.#b = _b;
            }

            //get 사용
            get Add(){
                return this.#a + this.#b
            }

            get A (){
                return this.#a
            }

            //set 사용
            set setA(_a) {
                this.#a = _a;
            }
        }
        const result = new cs(10, 9)

        result.setA = 7;    //set 사용

        console.log(result.Add) //get사용
        console.log(result.A)

        //16
        //7

    </script>
</body>

 

반응형

'JavaScript' 카테고리의 다른 글

[JavaScript] 상속(Inheritance), super()  (0) 2022.04.21
[JavaScript] throw(예외 발생)  (0) 2022.04.21
[JavaScript] Constructor 예제  (2) 2022.04.19
[JavaScript] new.target  (0) 2022.04.19
[JavaScript] Prototype  (0) 2022.04.19