• ES6 Classes

    2022. 9. 1.

    by. JJo 😊

    기존에는 prototype 기반으로 클래스를 만들었는데, ES6에서 class 라는 문법이 새로 추가가 되었다.

     

    👀 class 선언식

    // 기존
    function User(first, last) {
    	this.firstName = first;
    	this.lastNmae = last;
    }
    User.prototype.getFullName = function() {
    	return `${this.firstName} ${this.lastName}`
    }
    
    // ES6
    class User {
    	constructor(first, last) {
    		this.firstName = first;
    		this.lastNmae = last;
    	}
    	getFullName() {
    		return `${this.firstName} ${this.lastName}`
    	} 
    }
    
    const fullName = new User('eunhye', 'cho');
    console.log(fullName.getFullName()); // eunhye cho

    💡 constructor 메서드는 class 로 생성된 객체를 생성하고 초기화하기 위한 특수한 메서드이다. 이 메서드는 클래스 안에서 한 개만 존재할 수 있다.

    💡 메서드 사이엔 쉼표는 작성하지 않는다.

    💡 함수 선언과 클래스 선언의 중요한 차이점은 함수 선언의 경우 호이스팅이 일어나지만, 클래스 선언은 호이스팅이 되지 않는다. 클래스를 사용하기 위해서는 클래스를 먼저 선언해야 한다.

    let p = new Polygon(); // ReferenceError 
    class Polygon {}

     

    👀 class 표현식

    익명 클래스와 기명 클래스를 만들 수 있다.

    // 익명 클래스
    let User = class {
    	constructor(first, last) {
    		this.firstName = first;
    		this.lastNmae = last;
    	}
    }
    
    // 기명 클래스
    let User = class MyClass {
      sayHi() {
        alert(MyClass); // MyClass라는 이름은 오직 클래스 안에서만 사용할 수 있다.
      }
    }
    
    new User().sayHi(); // 제대로 동작(MyClass의 정의를 보여줌).
    alert(MyClass); // ReferenceError: MyClass is not defined, MyClass는 클래스 밖에서 사용할 수 없다.
    
    // 클래스 이름을 생략하고 부모클래스를 지정한 경우
    let name = class extends super_name{}
    
    // 클래스 이름과 부모클래스를 지정한 경우
    let name = class inner_name extends super_name{}

     

    👀 class 동적 생성

    필요에 따라 클래스를 동적으로 생성할 수 있다.

    function makeClass(phrase) {
      // 클래스를 선언하고 이를 반환함
      return class {
        sayHi() {
          alert(phrase);
        }
      }
    }
    
    // 새로운 클래스 생성
    let User = makeClass("Hello");
    
    new User().sayHi(); // Hello

     

    👀 class 상속/확장

    상속받는 클래스를 부모 클래스, 슈퍼 클래스라고 한다. 상속되는 클래스를 자식 클래스, 서브 클래스라고 한다.

     

    ES5 prototype 기반 상속

    function Cat(name) {
      this.name = name;
    }
    
    Cat.prototype.speak = function () {
      console.log(this.name + ' makes a noise.');
    };
    
    function Lion(name) {
      // `super()` 호출
      Cat.call(this, name);
    }
    
    // `Cat` 클래스 상속
    Lion.prototype = Object.create(Cat.prototype);
    Lion.prototype.constructor = Lion;
    
    // `speak()` 메서드 오버라이드
    Lion.prototype.speak = function () {
      Cat.prototype.speak.call(this);
      console.log(this.name + ' roars.');
    };
    
    let lion = new Lion('Samba');
    lion.speak();

    ES6 class 기반 상속

    class Vehicle {
    	constructor(name, wheel) {
    		this.name = name;
    		this.wheel = wheel;
    	}
    }
    const myVehicle = new Vehicle('운송수단', 2);
    console.log(myVehicle); // Vehicle {name: '운송수단', wheel: 2}
    
    class Bicycle extends Vehicle {
    	constructor(name, wheel) {
    		super(name, wheel)
    	}
    }
    const myBicycle = new Bicycle('삼천리', 2);
    const myBicycle2 = new Bicycle('세발', 3);
    console.log(myBicycle); // Bicycle {name: '삼천리', wheel: 2}
    console.log(myBicycle2); // Bicycle {name: '세발', wheel: 2}
    
    class Car extends Vehicle {
    	constructor(name, wheel, license) {
    		super(name, wheel)
    		this.license = license
    	}
    }
    const myCar = new Car('벤츠', 4, true);
    console.log(myCar); // Car {name: '벤츠', wheel: 4, license: true}

    💡 constructor는 부모 클래스의 constructor를 호출하기 위해 super 키워드를 사용할 수 있다.

    자식 클래스의 super은 부모 클래스의 생성자 메서드를 호출하며 부모 생성자 메서드에 받은 인자를 모두 전달한다. 이때, super 키워드를 생성자 메서드의 가장 상위 라인에 위치시켜야 한다. 나중에 호출하게 되면 this가 될 객체가 만들어지지 않아 에러가 발생한다.

     

    👀 메서드 오버라이딩

    특별한 사항이 없다면 자식 클래스는 부모 클래스에 선언된 메서드들을 그대로 상속받는다. 하지만 자식 클래스에 부모 클래스에 선언된 메서드와 이름이 동일할 경우 자식 클래스의 메서드가 호출되어 사용된다.

    // 부모 클래스
    class User {
    	constructor(name, hobby) {
    		this.name = name;
    		this.hobby = [hobby];
    	}
    	addHobby(hobby) {
    		this.hobby.push(hobby);
    		console.log('부모 클래스');
    	}
    }
    
    // 자식 클래스
    class Person extends User {
    	printHobby() {
        console.log(this.hobby.join(', '));
      }
    	addHobby(hobby) {
    	this.hobby.unshift(hobby);
    	console.log('자식 클래스');
      }
    }
    
    const user = new Person('eunhye', 'coding');
    user.addHobby('html'); 
    console.log(user.hobby); // ['html', 'coding'] 자식클래스

    부모 클래스와 이를 상속받은 자식 클래스에 addHobby( )라는 동일한 이름의 메서드가 선언되어 있다. 이 경우 프로토타입 동작 원리에 의해 자식 클래스의 addHobby( )가 실행된다.

    이럴 경우, super이라는 키워드를 사용하면, 부모 클래스에 정의된 메서드를 호출할 수 있다.

    // 부모 클래스
    class User {
    	constructor(name, hobby) {
    		this.name = name;
    		this.hobby = [hobby];
    	}
    	addHobby(hobby) {
    		this.hobby.push(hobby);
    	}
    }
    
    // 자식 클래스
    class Person extends User {
    	printHobby() {
        console.log(this.hobby.join(', '));
      }
    	addHobby(hobby) {
    	super.addHobby(hobby); // 부모 클래스에 있는 addHobby() 사용
      }
    }
    
    const user = new Person('eunhye', 'coding');
    user.addHobby('html'); 
    console.log(user.hobby); // ['coding', 'html']

     

    👀 getter와 setter

    메서드 앞에 get, set을 작성한다.

    let Person = class{ 
    	get getName(){ 
    		return this.name;
    	}
    	set setName(name){
    		this.name = name;
    	}
    } 
    let personObj = new Person(); 
    // () 를 명시하지 않는다. 
    personObj.setName = '야호'; 
    console.log(personObj.getName); // 야호
    728x90

    'Javascript' 카테고리의 다른 글

    데이터 불변성  (0) 2022.09.02
    DOMContentLoaded VS load  (0) 2022.09.02
    전개연산자  (0) 2022.08.28
    구조 분해 할당  (0) 2022.08.28
    let, const  (0) 2022.08.27

    댓글