Introduction to Classes

Class는 코드의 청사진이라고 생각하면 쉽다. Class는 객체지향적 프로그래밍을 위해 빠지지 않는 추상적인 개념이다. Class로 정의된 변수를 인스턴스변수라고 하는데, 인스턴스별로 class가 적용이 되고 class에 정의한 내용을 토대로 변수를 제어할 수 있다.

/**
 * class를 정의하여 객체를 만든다
 */
class User1 {
  constructor() {
    this.username = "Nicolas";
  }
  sayHello() {
    console.log(`Hello, I'm Nicolas`);
  }
}
/**
 * class를 new를 통해서 만들어진 변수를 `인스턴스`라고 한다.
 */
const sexyUser1 = new User1();
const uglyUser1 = new User1();
sexyUser1.sayHello();
uglyUser1.sayHello();

/**
 * 사실 class 없이도 object정의만으로 class와 같은 동작을 
 * 할 수 있다. 하지만 class가 좀더 직관적이고 체계적이고
 * 유지 보수가 훌륭하기도하며 객체지향적인 프로그램을 설계
 * 하는데에 있어 없어서는 안될 추상적 개념이다.
 */
const baseObject = {
  username: "Nicolas",
  sayHello: function () {
    console.log("Nicolas");
  },
};

const sexyUser2 = baseObject;
const uglyUser2 = baseObject;
sexyUser2.sayHello();
uglyUser2.sayHello();

/**
 * 객체생성에 인수를 주어 class 내부맴버의 초기값을 넣을 수
 * 있고 this라는 키워드를 사용하여 class로 생성한 인스턴스
 * 마다 정의된 맴버를 독립적으로 컨트롤 할 수 있다.
 */
class User3 {
  constructor(name) {
    this.username = name;
  }
  sayHello() {
    return `Hello, my name is ${this.username}`;
  }
}

const sexyUser3 = new User3("Nico");
console.log(sexyUser3.sayHello());

Extending Classes

this는 class를 자체를 가리키는 키워드이다. 인스턴스변수는 class를 가지고 있다. 그리고 변수가 외부로 부터 전달받은 데이터를 가지고 class 내부의 맴버 데이터를 조작하기위해 접근하는 키워드이기도 한다.

Extends 키워드는 다른 프로그래밍 언어에서 상속이라고 부르는 개념이다. 부모 class 본연의 기능을 사용가능하면서 자식 class만의 새로운 기능을 확장하기 위해서 주로 사용한다.

/**
 * 이전 User class의 기능을 확장하여 아래와 같이 함수를 정의하였다.
 * 이처럼 class는 확장 및 유지보수도 쉽고 코드가 더 늘었음에도 정돈된
 * 모습을 볼 수 있다.
 */
class User {
  constructor(name, lastName, email, password) {
    this.username = name;
    this.lastName = lastName;
    this.email = email;
    this.password = password;
  }
  sayHello() {
    console.log(`Hello, my name is ${this.username}`);
  }
  getProfile() {
    console.log(`${this.username} ${this.email} ${this.password}`);
  }
  updatePassword(newPassword, currentPassword) {
    if (currentPassword == this.password) {
      this.password = newPassword;
    } else {
      console.log("Can't change password.");
    }
  }
}

const sexyUser = new User("Nico", "Serrano", "nico@com", "1234");

sexyUser.getProfile();
console.log(sexyUser.password);

sexyUser.updatePassword("hello", "111111");
console.log(sexyUser.password);

/**
 * 이번엔 User class를 확장하여 Admin class를 정의한 것이다. 여기서
 * Admin은 User본연의 기능을 유지하면서 Admin만이 가지는 기능을 정의한다.
 */
class Admin extends User {
  deleteWebsite() {
    console.log("Deleting the whole website...");
  }
}

const sexyAdmin = new Admin("Nico", "Serrano", "nico@com", "1234");
sexyAdmin.deleteWebsite();
console.log(sexyAdmin.email);

Super

JS는 기본적으로 자식 class가 생성자를 정의하면 부모 생성자를 잃게 된다. 그렇기에 자식 class에서 super()를 자식 생성자안에서 호출하여 부모 생성자를 호출한다.

class User {
  constructor({ username, lastName, email, password }) {
    this.username = username;
    this.lastName = lastName;
    this.email = email;
    this.password = password;
  }
  sayHello() {
    console.log(`Hello, my name is ${this.username}`);
  }
  getProfile() {
    console.log(`${this.username} ${this.email} ${this.password}`);
  }
  updatePassword(newPassword, currentPassword) {
    if (currentPassword == this.password) {
      this.password = newPassword;
    } else {
      console.log("Can't change password.");
    }
  }
}

const sexyUser = new User({
  username: "Nico",
  lastName: "Serrano",
  email: "nico@com",
  password: "1234",
});

/**
 * 자식 class안에 생성자를 다시 정의하면 부모 class의
 * 생성자를 잃게 된다. 부모 생성자도 사용하기 위해서는
 * 자식 class 생성자안에 `super()`라는 함수를 호출한다.
 * `super()`함수는 부모 class의 생성자를 호출한다.
 */
class Admin extends User {
  constructor({ username, lastName, email, password, superAdmin, isActive }) {
    super({ username, lastName, email, password });
    this.superAdmin = superAdmin;
    this.isActive = isActive;
  }
  deleteWebsite() {
    console.log("Deleting the whole website...");
  }
}

const admin = new Admin({
  username: "Nico",
  lastName: "Serrano",
  email: "nico@com",
  password: "1234",
  superAdmin: true,
  isActive: true,
});

What this is ‘this’