JS 강의 필기 + 추가
object-oriented programming
class: template 개념. fields(속성)과 method(행동)으로 이루어짐
object: an instance of a class
constructor: 생성자. 이를 통해서 object를 만들 때 필요한 데이터를 전달
class Person {
constructor(name, age) {
// fields
this.name = name;
this.age = age;
}
speak() { // method
console.log(`${this.name}: hello!`);
}
}
const phin = new Person('phin', 30); // object 생성
console.log(phin.name);
consoole.log(phin.age);
phin.speak();
getter and setter
getter를 정의하면 constructor 안에 있는 this.age는 데이터를 읽어오는 게 아니라 getter를 호출한다.
setter를 정의하면 constructor 안에 있는 = age 는 메모리에 있는 값을 바로 할당하는 게 아니라 setter를 호출한다.
class User {
// field 3가지: firstName, lastName, _age
constructor(firstName, lastName, age) {
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
}
get age() {
return this._age; // getter와 setter에 이런 식으로 이름을 다르게 줘야 됨
}
set age(value) { // 값을 필터링해 넣기
this._age = value < 0 ? 0 : value; // value가 음수면 0을 쓰고, 아니면 value를 쓰겠다
}
}
const user1 = new User('Steve', 'Jobs', -1);
console.log(user1.age);
그래서 getter와 setter 안에서는 생성자에 사용한 것과 동일한 변수명을 쓰면 안 된다. recursion을 무한 반복하는 셈이 되기 때문.
class User {
constructor(firstName, lastName, age) {
this.firstName = firstName;
this.lastName = lastName;
this.age = age; // 여기에 쓴 변수명을 getter와 setter에 그대로 쓰면 안 된다.
}
get age() {
return this.age; // 이렇게 쓰면 maximun call stack size exceeded 에러 남.
}
set age(value) {
this.age = value; // 이렇게 쓰면 전달된 value를 메모리에 업데이트하는 게 아니라 setter를 호출하는 것임
}
}
const user1 = new User('Steve', 'Jobs', -1);
console.log(user1.age);
사용자가 잘못된 값을 넣었을 때 값을 필터링해 넣는 게 아니라 에러 메시지를 띄우고 싶다면
set age(value) {
if (value < 0) {
throw Error('age cannot be negative') // Uncaught Error: age cannot be negative 이렇게 출력됨
}
this._age = value;
}
Inheritance(상속)
a way for one class to extend another class
class Shape {
constructor(width, height, color) {
this.width = width;
this.height = height;
this.color = color;
}
draw() {
console.log(`drawing ${this.color} color of`);
}
getArea() {
return this.width * this.height;
}
}
class Rectangle extends Shape {} // 이렇게만 써도 Shape에 있는 모든 fields와 methods를 포함
const rectangle = new Rectangle(20, 20, 'blue');
rectangle.draw();
console.log(rectangle.getArea());
class Rectangle은 Shape를 그대로 상속한 상태다. 아래는 Shape를 상속하고 일부 바꾸기도 하는, overriding한 class Triangle이다.
class Triangle extends Shape {
draw() {
// super.draw(); // 부모의 draw도 실행
console.log('▲');
}
getArea() {
return (this.width * this.height) / 2;
}
toString() {
return `Triangle, color: ${this.color}`
}
}
const triangle = new Triangle(20, 20, 'red');
triangle.draw(); // ▲
console.log(triangle.getArea());
instanceOf: class checking
왼쪽의 object가 오른쪽 class의 instance인지 판별해서 true or false를 return
console.log(rectangle instanceof Rectangle); // true
console.log(triangle instanceof Rectangle); // false
console.log(triangle instanceof Shape); // true
console.log(triangle instanceof Object); // true
모든 class들은 object라는 기본 class를 상속한다. class Triangle에서는 이 object에 있는 toString이라는 method를 overriding해서 원하는 대로 변경했다. overriding하지 않고 그대로 상속받아 사용하면 [object object]로 출력된다.
console.log(triangle.toString()); // Triangle, color: red 출력
super
파생 클래스에서 super() 함수가 먼저 호출되어야 this 키워드를 사용할 수 있음. 그렇지 않으면 Uncaught ReferenceError 발생(Must call super constructor in derived class before accessing 'this' or returning from derived constructor).
class Polygon {
constructor(height, width) {
this.name = 'Polygon';
this.height = height;
this.width = width;
}
sayName() {
console.log('Hi, I am a ', this.name + '.');
}
}
class Square extends Polygon {
constructor(length) {
// this.height // Uncaught ReferenceError
super(length, length);
this.name = 'Square';
}
get area() {
return this.height * this.width;
}
set area(value) {
this.area = value;
}
}
let square = new Square(20);
console.log(square); // Square {name: "Square", height: 20, width: 20}
'JS' 카테고리의 다른 글
JS - array (0) | 2020.12.24 |
---|---|
JS - object (0) | 2020.12.23 |
JS - function (0) | 2020.12.21 |
JS - operator (0) | 2020.12.21 |
JS - variable (0) | 2020.12.19 |