ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Javascript] Class(클래스) 기본
    Front-End(Web)/Javascript 2020. 12. 16. 22:56
    반응형

    위코드 Replit 과제중, Class 개념에 대해 정리가 필요하다고 생각해서 글을 쓰게 되었다.


    📒 class 란?

    - 객체지향(OOP, Object-Oriented Programming)

    객체지향 프로그래밍이란, 프로그램을 객체(Object)들로 구성하고 서로 상호작용을 통해 구현하는 방법을 의미한다.

    객체에 변수나 함수를 저장한 뒤 이를 반복적으로 사용하고자 하는 개념으로, 이 객체를 편리하게 생성하는 템플릿이 바로 Class인 것이다.

     

    - class 정의

    class를 "특별한 함수" 라고 설명한다. class 선언과 표현식으로 정의할 수 있다.(실제로 ES6 전에는 함수가 class를 대체했다.)

     

    1) class 선언

    ES6부터 class 개념이 도입되면서, class는 아래와 같이 'class 클래스명' 구문으로 생성할 수 있다.

    class Rectangle {			// Rectangle 이라는 이름의 class
      constructor(height, width) {
        this.height = height;
        this.width = width;
      }
    }

    class에는 반드시 constructor(생성자)라고 하는 키워드를 사용해야 한다. (밑의 class 구조에서 자세히 알아보장!!)

    또한, class는 함수와 달리 Hoisting이 적용되지 않아 먼저 선언을 해야한다.

     

    2) class 표현식

    // unnamed
    let Rectangle = class {
      constructor(height, width) {
        this.height = height;
        this.width = width;
      }
    };
    console.log(Rectangle.name);
    // 출력: "Rectangle"
    
    // named
    let Rectangle = class Rectangle2 {
      constructor(height, width) {
        this.height = height;
        this.width = width;
      }
    };
    console.log(Rectangle.name);
    // 출력: "Rectangle2"

    변수에 class 를 지정하는 방법이다. Class 표현식은 이름을 변수명으로 대체가능하며, 이름은 'Class.name' 속성으로 확인가능하다.

     

    - class 기본 문법

    class User {			// 클래스명
      constructor(name) {		// 생성자 함수
        this.name = name;
      }
      sayHi() {			// 메소드(함수)
        alert(this.name);
      }
    }
    
    let user = new User("John");	// 인스턴스
    user.sayHi();

    1) 클래스명 : User 에 해당하는 부분. 표현식의 경우 변수명으로 대체될 수 있다. (클래스명은 반드시 대문자로 시작, CammelCase)

     

    2) constructor(생성자) 함수 : constructor(name) { this.name = name; } 에 해당하는 부분. 

    클래스 내 함수(메서드)에서 사용할 인자(argument)들을 설정하는 부분이다.

    왼쪽은 this(클래스로 생성된 인스턴스)의 'name' property를 의미, 오른쪽은 인스턴스에서 입력받을 생성자값을 의미한다.

     

    3) Method(메서드) : sayHi() { alert(this.name); } 에 해당하는 부분. 생성자를 활용한 다양한 기능을 구현하는 함수들을 의미한다.

     

    4) Instance(인스턴스) : let user = new User('John') 에 해당하는 부분. 클래스를 통해 생성된 객체를 의미한다.

    'user' 가 객체명이 되고, new 클래스명(키워드) 로 선언할 수 있다. ('John' 키워드 -> constructor 함수 -> 'name' property에 할당)


    📒 Prototype 에 대한 이해

    Javascript에서 함수를 정의하면, 함수 안에 Prototype Object도 같이 생성된다. (객체를 생성해도 [[Prototype]] 내부 프로퍼티가 존재)

    function Foo() {
    
    }

    • prototype : 생성자 함수(Foo)를 통해 형성되는 모든 객체(인스턴스)가 공유할 원형(의 정보)를 담고 있다.
    • constructor : 내가 선언한 생성자 함수(Foo) 자체를 의미한다. new 구문을 쓰면 이 생성자 함수를 실행해서 객체가 생성된다.
    • __proto__ : [[Prototype]] 링크를 담고 있는 객체로, 생성자 함수(Foo)의 prototype을 참조할 수 있는 경로이다.
    const f1 = new Foo();
    const f2 = new Foo();
    Object.getPrototypeOf(f1) === Foo.prototype; // true

     

    Foo라는 생성자 함수는 Foo.prototype 객체를 형성하고, 여기에 함수에 관한 정보들이 저장된다. (클래스에선 메소드들이 해당되겠죠?)

    new 구문을 통해 새로 생성된 인스턴스(f1, f2)들은, [[Prototype]] 링크를 통해 Foo.prototype 객체와 연결된다.

    이 경로를 통해, 클래스(Foo)와 인스턴스(f1, f2)는 객체간 연결이 성립되고, 클래스에 내장된 다양한 정보들을 공유할 수 있는 것이다. 


    📒 class의 다양한 기능들

     

    1. Getter & Setter

    class에서 사용되는 메소드의 일종이다. 인스턴스를 통해 입력된 값을 확인(get)한뒤 오류여부에 따라 값을 조정(set)하는 기능을 제공한다.

    class User {
        constructor(firstName, lastName, age) {
            this.firstName = firstName;
            this.lastName = lastName;
            this.age = age;
        }
        get age() {        		 // getter : age값을 _age에 받음(변수명 반드시 다르게 설정!)
            return this._age;
        }
        set age(value) {   		 // setter : _age값 판단. 음수는 0, 나머지는 value(value가 입력값)
            this._age = value < 0 ? 0 : value;
        }
    }
    
    const user1 = new User('taehyung', 'Kim', -1);
    console.log(user1.age);		// 0

     

    2. Public, Private Fields

    클래스 안에서 자체적인 변수들을 선언하는 경우이다. Public 변수는 전역에서 호출 가능하나, Private 변수(#)은 클래스 외부에선 호출불가.

    class Experimet {
      publicfield = 2;    
      #privatefield = 1;  
    }
    
    const experiment = new Experimet();
    console.log(experiment.publicfield);		// 2 (외부접근 가능)
    console.log(experiment.privatefield);		// undefined (외부접근 불가)

     

    3. Static properties and methods

    클래스 자체적으로만 사용될 property 나 method 를 지정하는 경우이다. (클래스 자체에선 사용가능하나, 인스턴스에선 사용불가)

    class Article {
        static publisher = 'Dream Coding';
        constructor(articleNum) {
            this.articleNu = articleNum;
        }
        static printPublisher() {
            console.log(Article.publisher);		// Dream Coading (클래스 내 호출가능)
        }
    }
    
    console.log(Article.publisher);     // Dream Coading (클래스 자체에서 호출가능)
    
    const article1 = new Article(1);
    console.log(article1.publisher);    // undefined (인스턴스에선 호출 불가능!)

    * Private Field(#) 나 Static 은 클래스에서 한정적으로 이용되는 설정값에 유용하며, 최근에 적용된 기능으로 사용빈도가 아직 낮다!

     

    4. Inheritance

    기존 클래스를 다른 클래스로, 말 그대로 '상속' 시키는 방법이다. (React에서 밥먹도로 쓴 'class App extends React' 가 스쳐지나갔다!🤩)

    // 기존 클래스 (도형 그리기)
    class Shape {
        constructor(w,h,c) {
            this.width = w;
            this.height = h;
            this.color = c;
        }
        draw() {
            console.log(`drawing ${this.color} color of`);
        }
        getArea() {
            return this.width * this.height;
        }
    }
    
    // 상속 : 'extends'로 기존 클래스의 속성, 메서드를 새 클래스로 복제
    class Rectangle extends Shape {}    
    const rectangle = new Rectangle(20,20,'blue');
    console.log(rectangle.getArea());		// 400
    
    // 다양성 : 단순 복제뿐 아니라, 가져온 메서드의 수정도 가능하다
    class Triangle extends Shape {
    	// 메서드 수정방법 : 1) super(상위 Shape 클래스)의 getArea()를 받아와서, 2) return 함수로 수정
        getArea() {                     
            super.getArea();
            return (this.width * this.height) / 2;
        }
    }
    const triangle = new Triangle(20,20,'red');
    console.log(triangle.getArea());		// 200
    

     

    5. Obj instanceof Class

    Obj 가 Class 로부터 형성됬는지 여부를 체크하는 기능. true/false를 반환한다. (inheritance 관계도 포함된다.)

    // 4번 Class들 참고
    
    console.log(rectangle instanceof Rectangle);    //t
    console.log(triangle instanceof Rectangle);     //f
    console.log(triangle instanceof Triangle);      //t
    console.log(triangle instanceof Shape);         //t(inheritance)
    console.log(triangle instanceof Object);        //t(모든 Object 클래스)

    😃 결론

    Class는 자바스크립트 이론공부를 할 때 거의 이해를 못 한채로 넘어갔고(super, this, prototype 등등!!!),

    React를 독학할 때도 클래스형 컴포넌트를 사용하며 포스팅 필요성을 절실하게 느끼고 있었다. (이해안되는 구문들이 매우 많았다.😢)

     

    Class가 먼저 함수의 일종이지만, 그 목적자체는 객체를 '형성'함에 있다는 것을 확실히(어쩌면 새로이) 알게 되었다.

    객체지향이란 개념도 이번 기회에 확실히 정립할 수 있었고, 이를 실현시키는 prototype 프로퍼티에 대해서도 많은 고민을 한 기회였다.

     

    클래스형 컴포넌트를 제작할 때 super(props)를 사용하는것만 봐도, 클래스가 참 어렵고 그만큼 확실히 공부해야 한다고 생각했다.

    이 포스팅이 클래스 이론의 절반도 채 안되겠지만, 앞으로 클래스를 다룸에 있어 가장 기초적인 개념들로 나와 지나치시는 많은 분들께 도움이 되었으면 하는 바램으로 글을 마무리한다.

     

    출처]
    - Classes MDN : https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Classes
    - 모던 Javascript 튜토리얼 : https://ko.javascript.info/class  


    - adam2님의 블로그 : https://velog.io/@adam2/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-Prototype-%EC%99%84%EB%B2%BD-%EC%A0%95%EB%A6%AC

    반응형
Designed by Tistory.