자바스크립트 Class

김명주·2023년 2월 1일
0

Class

Javascript는 기본적으로 prototype 기반 언어이지만, class를 사용할 수 있다.

  1. prototype
// 흔히 아는 배열 데이터 생성 방법
const fruits = ['apple','banana','cherry']


// new라는 키워드로 시작하는 함수를 생성자 함수라고 함.
// 그 함수의 인자로 원하는 내용을 집어넣기
// 이렇게 만들어진 걸 인스턴스(instance)라고 부른다.
const fruits = new Array('apple','banana','cherry')


// Array객체에서 프로토타입으로 carllis라는 메소드를 등록한 것.
Array.prototype.carllis = function(){
    console.log(this)
}
// 배열데이터에서 쓸수 있는 하나의 메소드가 된 것
fruits.carllis(); //['apple','banana','cherry']
  1. 다른 객체의 메소드 재활용

    'call()' 을 이용해서 다른 객체에 있는 메소드를 재활용 할 수 있다.

    그러나 재활용 할 대상이 여러개이거나, 또 재활용 할 때마다 메소드가 있는 객체를 불러와야 하기에 비효율 적이다.
// 다른 객체 안에 있는 메소드 재활용 하기
const carllis = {
    firstName: 'Carllis',
    lastName:'kim',
    getFullname: function(){
        // 객체 데이터 내부에서 일반 함수를 통해 메소드를 만들게 되면
        // this라는 키워드를 통해서 해당하는 객체에 접근할 수 있다.
        // 호출되는 대상에 접근하는 것
        return `${this.firstName} ${this.lastName}`
    }
}
const neo = {
    firstName: 'Neo',
    lastName:'Anderson',
}

console.log(carllis.getFullname()) // Carllis kim
console.log(carllis.getFullname.call(neo)) // Neo Anderson
// neo라는 객체 데이터가 carllis객체의 getFullname 메소드를 빌려서 호출

prototyper과 생성자 함수를 이용해 메소드와 인스턴스 객체를 만들어서 사용하면 훨씬 간편하고 효율적이게 만들 수 있다.

    // 주의 할 점, 반드시 첫글자는 대문자로
    // 위의 getFullName 메소드를 함수만 가지고 구현
    function User(first, last){
        this.firstName = first;
        this.lastName = last;
    }
    // 이 부분에선 화살표 함수를 사용하면 안됨. this가 가리키는 방향이 달라지기 때문
    // prototype의 메소드를 만들땐 반드시 일반함수로

    // 이제 User를 생성자 함수로 만들어진 인스턴스 객체는 getFullName 메소드를 사용할 수 있다.
    User.prototype.getFullName = function(){
        return `${this.firstName} ${this.lastName}`
    }

    // 단순히 호출만 하는것이 아닌 new 키워드를 통해 호출해야 함.
    // 인스턴스 객체 생성
    const carllis = new User('Carllis', 'Kim')
    const neo = new User('neo', 'Anderson')

    console.log(carllis) // User {firstName: 'Carllis', lastName: 'Kim'}
    console.log(neo) // User {firstName: 'neo', lastName: 'Anderson'}
    console.log(carllis.getFullName())  // Carllis Kim
    console.log(neo.getFullName()) // neo Anderson
  1. ES6 Class 기본 문법
// prototype을 이용해 객체 만들기
function User(first, last){
    this.firstName = first;
    this.lastName = last;
}

User.prototype.getFullName = function(){
    return `${this.firstName} ${this.lastName}`
}


const carllis = new User('Carllis', 'Kim')
const neo = new User('neo', 'Anderson')


console.log(carllis) // User {firstName: 'Carllis', lastName: 'Kim'}
console.log(neo) // User {firstName: 'neo', lastName: 'Anderson'}
console.log(carllis.getFullName())  // Carllis Kim
console.log(neo.getFullName()) // neo Anderson

// Class를 이용해 객체 만들기
// 위의 prototype을 이용한것과 동일한 기능을 한다

class User{
    // constructor 키워드가 기존에 우리가 만든 User 함수 역할을 해줌
    constructor(first, last){
        this.firstName = first;
        this.lastName = last;
    }
    getFullName(){
        return `${this.firstName} ${this.lastName}`
    }
}



const carllis = new User('Carllis', 'Kim')
const neo = new User('neo', 'Anderson')


console.log(carllis) // User {firstName: 'Carllis', lastName: 'Kim'}
console.log(neo) // User {firstName: 'neo', lastName: 'Anderson'}
console.log(carllis.getFullName())  // Carllis Kim
console.log(neo.getFullName()) // neo Anderson
  1. Getter, Setter
    • Getter -> 어떠한 값을 얻는 용도로 사용하는 메소드
    • Setter -> 값을 지정하는 용도로 사용하는 메소드
// Getter
class User{
    // constructor 키워드가 기존에 우리가 만든 User 함수 역할을 해줌
    constructor(first, last){
        this.firstName = first;
        this.lastName = last;
    }
    // get 키워드는 메소드 앞에 붙여서 사용하는 것
    // get 키워드를 붙이면 값을 얻어내는 용도의 함수인 Getter가 되는것
    // 그렇게 되면 그 메소드는 마치 속성처럼 사용할 수 있다.
    get fullName(){
        return `${this.firstName} ${this.lastName}`
    }
}
const carllis = new User('Carllis', 'Kim')

console.log(carllis.fullName)  // Carllis Kim

carllis.firstName ='alex'

console.log(carllis.fullName)  // alex Kim



// Setter
class User{
    // constructor 키워드가 기존에 우리가 만든 User 함수 역할을 해줌
    constructor(first, last){
        this.firstName = first;
        this.lastName = last;
    }
    // get 키워드는 메소드 앞에 붙여서 사용하는 것
    // get 키워드를 붙이면 값을 얻어내는 용도의 함수인 Getter가 되는것
    // 그렇게 되면 그 메소드는 마치 속성처럼 사용할 수 있다.
    get fullName(){
        return `${this.firstName} ${this.lastName}`
    }
    // set 키워드도 메소드 앞에 붙여서 사용, 그렇게 되면 그 메소드는 Setter가 된다.
    // 값을 지정할때 동작하는 메소드
    set fullName(value){
        console.log(value);
        // 기준을 정해 그 기준으로 문자열을 나눠서 배열로 반환하는 메소드 split()
        [this.firstName, this.lastName] = value.split(' ')
    }
}
const carllis = new User('Carllis', 'Kim')

console.log(carllis.fullName)  // Carllis Kim

carllis.fullName = 'neo anderson'

console.log(carllis) // neo anderson
  1. 정적 메소드

간단히 말하면 클래스 자체에서 사용할 수 있는 메소드.

class User{
    constructor(first, last){
        this.firstName = first;
        this.lastName = last;
    }
    // 이러한 타입의 메소드는 prototype 메소드
    // 별도의 인스턴스에서 호출해야 한다.
    getFullName(){
        return `${this.firstName} ${this.lastName}`
    }
    // 이 메소드는 정적 메소드라고 표시해주는 static 키워드
    // 이 메소드는 이제 인스턴스가 아닌 클래스에서 사용할 수 있다.
    static isUser(user){
        if(user.firstName && user.lastName){
            return true;
        }else{
            return false;
        }
    }
}


const carllis = new User('Carllis', 'Kim')
const neo = new User('neo', 'Anderson')

// prototype 메소드는 인스턴스에서 사용하는 것.
console.log(carllis.getFullName()) 
console.log(neo)
// 클래스 자체에서 사용할 수 있는 정적 메소드
console.log(User.isUser(carllis)) //true
  1. 클래스의 상속
class Vehicle{
    constructor(acceleration = 1){
        this.speed = 0;
        this.acceleration = acceleration
    }
    accelerate(){
        this.speed += this.acceleration
    }
    decelerate(){
        if(this.speed <= 0){
            console.log('정지')
            return
        }
        this.speed -= this.acceleration
    }
}


// extends 키워드를 통해서 Vehicle 클래스의 기능을 상속하는 것(가져와서 사용할 수 있게)
class Bicycle extends Vehicle{
    constructor(price = 100, acceleration){
        // 1. super(): 부모-class의 생성자(constructor)를 참조한다.
        // 2. super.method() : 부모-class의 prototype-method를 참조한다.
        // super의 기술적 의미
        // -> 상속된(자식) class에 요소 추가 시 새로 추가되는 parameter를 정의하려면
        // 기존(부모)-class constructor를 다시 정의해 주어야 한다.
        // 이 과정에서 생기는 중복되는 코드가 발생해, error발생 확률 증가, 메모리 낭비 등 매우 비효율적인 낭비가 생긴다.
        // 이러한 부분을 super로 해결할 수 있다.

        // 부모 클래스의 속성 값을 불러와 초기값을 세팅하는 역할인 super
        super(acceleration)
        this.price = price
        this.wheel = 2;
    }
    
}
// 생성자 함수를 통해 인스턴스 생성
const bicycle = new Bicycle(300, 2)

// bicycle 객체가 Vehicle 클래스를 상속한 Bicycle을 통해 만들어 져서
// Bicycle 클래스에는 없던 speed와 acceleration 속성도 가지고 있음
console.log(bicycle) // Bicycle{acceleration: 2 price: 300 speed: 0 wheel: 2}


// instanceof => 앞의 데이터가 뒤쪽의 클래스에서 인스턴스로 만들어져있는지 확인하는 키워드
console.log(bicycle instanceof Bicycle) //  true

// Bicycle 클래스 자체가 Vehicle 클래스를 상속햇기 때문에 true
console.log(bicycle instanceof Vehicle) //  true


class Car extends Bicycle{
    constructor(license, price, acceleration){
        // 생성할때 아무런 매개변수도 없다면
        // 기본값으로 price=100, acceleration=1 이라는 값을 넣어준다
        super(price, acceleration)
        this.license = license
        this.wheel = 4;
    }
    accelerate(){
        if(!this.license){
            console.error('무면허')
            return
        }
        this.speed += this.acceleration
        console.log('가속', this.speed)
    }
    
}

const carA = new Car(true, 7000, 10)
const carB = new Car(false, 4000, 6)

console.log(carA) // Car {speed: 0, acceleration: 10, price: 7000, wheel: 4, license: true}
console.log(carB) // Car {speed: 0, acceleration: 6, price: 4000, wheel: 4, license: false}

class Boat extends Vehicle{
    constructor(price, acceleration){
        super(acceleration)
        this.price = price
        this.motor = 1
    }
}

const boat = new Boat(10000, 5)
console.log(boat) // Boat {speed: 0, acceleration: 5, price: 10000, motor: 1}
  1. 간단한 상속 예제
class A{
    constructor(){

    }
}
class B extends A{
    constructor(){
        super();
    }
}
class C extends B{
    constructor(){
        super();
    }
}

// 인스턴스 생성
const a = new A()
const b = new B()
const c = new C()


// 데이터가 특정 클래스의 인스턴스인지 확인하는 키워드 instanceof
// 클래스의 부모 클래스와 비교해도 true가 나온다
console.log(a instanceof A) // true
console.log(a instanceof B) // false


// 특정 인스턴스의 구조를 다른 클래스와 비교하기
console.log(c.constructor === A) // false
profile
개발자를 향해 달리는 사람

0개의 댓글