Class !
객체를 생성할 수 있는 템플릿 (청사진, 틀)
밀접하게 연관있는 요소들을 객체로 만들어 객체끼리 호환가능하게 프로그래밍 하는 것.
데이터 - 데이터를 조작하는 코드를 묶어서 추상화.
Instance : 클래스를 통해 만든 객체.
예시
class Fruit {
constructor(name, emoji) {
this.name = name;
this.emoji = emoji;
}
display = () => { // 클래스 안에서 메소드 작성법, 인스턴스레벨의 메소드
console.log(`${this.name} : ${this.emoji}`); // 인자를 같이 쓰고 싶다면 마찬가지로 this 써야한다.
};
}
const apple = new Fruite(‘apple’, ‘!’); //apple이라는 인스턴스 생성
기본 형태에 익숙해 져야 한다.
- constructor 메서드는 class 로 생성된 객체를 생성하고 초기화하기 위한 특수한 메서드.
- this의 활용.
- 메소드의 작성법과 메소드 안에서 인자를 활용하는 법.
- apple은 Fruit 클래스의 인스턴스이다. 클래스를 이용해서 인스턴스들을 찍어낸다.
함수 선언과 클래스 선언의 중요한 차이점은 함수의 경우 정의하기 하기 전에 호출할 수 있지만, (호이스팅 : 표현식 제외)
클래스는 반드시 정의한 뒤에 사용할 수 있다는 점입니다. (선언은 호이스팅이 되지만 값의 초기화는 되지 않기 때문. 아래 코드는 실행불가.)
const p = new Rectangle(); // ReferenceError
class Rectangle {}
Static ! 재사용성을 높이는 방법
클래스를 위한 정적(static) 메서드.
클래스 레벨에서 공통적으로 사용할 수 있는 속성, 함수를 만듭니다.
각각의 객체마다 서로 다른 데이터들을 가지고 있을 때가 아닌,
모든 객체가 동일하게 참조해야 하는 데이터가 있을때 유용하게 쓸 수 있는 속성입니다.
정적 메서드는 클래스의 인스턴스화 없이 호출되며, 클래스의 인스턴스에서는 호출할 수 없습니다.
정적 속성은 캐시, 고정 환경설정 또는 인스턴스 간에 복제할 필요가 없는 기타 데이터에 유용합니다.
정적 메서드는 어플리케이션(application)을 위한 유틸리티(utility) 함수를 생성하는 데 주로 사용됩니다.
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
static displayName = "Point"; // 정적 속성
static distance(a, b) { // 정적 메소드
const dx = a.x - b.x;
const dy = a.y - b.y;
return Math.hypot(dx, dy);
}
}
const p1 = new Point(5, 5);
const p2 = new Point(10, 10);
p1.displayName; // undefined
p1.distance; // undefined
console.log(Point.displayName); // "Point"
console.log(Point.distance(p1, p2)); // 7.0710678118654755
static 에서는 주어진 데이터가 채워지지 않은 상태이기 때문에 this는 사용할 수 없습니다.
=> 원래 this 자리에는 new 인스턴스가 들어가니까.
static화 하는 것과 public으로 직접 전달하는 것의 차이.
class Fruite {
type = "과일";
constructor(name) {
this.name = name;
}
}
class Fruite2 {
static type = "과일";
constructor(name) {
this.name = name;
}
}
const banana = new Fruite("바나나");
const apple = new Fruite2("사과");
console.log(banana.type); //"과일"
console.log(apple.type); // undefined
console.log(Fruite2.type);//"과일"
=>> 모든 인스턴스에서 동일하게 값을 뽑을 수 있지만 인스턴스를 생성 할 때마다 자료가 계속 들어가기 때문에 비효율적입니다.
class ClassWithStaticMethod {
static staticProperty = "someValue";
static staticMethod() {
return "static method has been called.";
}
static {
console.log("Class static initialization block called");
}
}
console.log(ClassWithStaticMethod.staticProperty);
console.log(ClassWithStaticMethod.staticMethod());
// Class static initialization block called
// someValue
// static method has been called.
Field
현재 이를 지원하는 브라우저는 제한적인 상태입니다. Babel 과 같은 시스템을 이용한다면 이 기능을 사용해 볼 수 있습니다.
클래스 안에 있는 property, 그것에 대한 접근 제한법.
외부에서 수정할 수 없도록 숨겨놓는 느낌.
private(#), public(기본)
#을 붙인 데이이터는 외부에서 접근이 불가함.
class Fruit {
type = '과일'; // public!
constructor(name, emoji) {
this.#name //private!
this.#emoji
}
static make() { // 클래스 레벨의 프로퍼티와 메소드로, 인스턴스를 생성해도 포함되지 않는다.
return new Fruit(‘banana’ , “?”)
}};
name, emoji는 contractor 안에서, 즉 외부로 부터 전달받은 인자로 채워지게 되고,
type의 경우는 field로 지정되어 있기 때문에
new Fruit로 만들어서 인자로 전달 해주지않아도 프로퍼티로 포함되어 있다.
이때 외부에서 변경이 불가능하게 하고 싶다면 인자에 #을 붙이면 된다.
Getter & Setter
접근자 프로퍼티. (Accessor Property)
변수처럼 보이지만 실제로는 함수를 말합니다.
getter
동적으로 계산한 값을 반환하는 속성이 필요하거나, 명시적인 함수 호출 없이도 객체의 내부 변수 상태를 반영하는 값을 나타내고 싶은 경우, JavaScript에서는 이런 경우 사용할 수 있도록 접근자(getter)라는 기능을 제공합니다.
getter는 어떤 프로퍼티(property)에 접근할 때마다 그 값을 계산하도록 해야 하거나 내부 변수의 상태를 명시적인 함수 호출 없이 보여주고 싶을 때 사용합니다.
class Student {
constructor (firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
fullName() {
return `${this.lastName} ${this.firstName}`
}};
const student = new Student(‘수지’ , ‘김’)
student.firstName // 수지
student.fullName() // 김수지.
=> 단순히 상태를 호출하기 위함인데, 프로퍼티가 아닌, 함수로 굳이 호출하는게 어색하게 느껴집니다.
하지만 this.fullName = `${this.lastName} ${this.firstName}
이렇게 프로퍼티로 직접 지정을 했을 경우에는 값이 업데이트 되지 않습니다.
중간에 student.firstName = “안나” 라고 값을 수정해도 fullName은 변경값이 반영되지 않고 그대로 김수지로 남는 것.
이것이 업데이트 되는 값으로 지정하기 위해서는
get fullName() {
return `${this.lastName} ${this.firstName}
}
이렇게 하면 됩니다.
student.fullName() 이렇게 함수호출을 하는것이 아니라,
student.fullName 이렇게 상태를 불러내면 됩니다.
함수지만 고정된 값이 아니라, 호출하는 시점에 데이터를 만들어서 리턴합니다.
특정한 일을 하는 함수를 만드는 게 아닌, 속성에 접근하듯이 사용하고 싶을 때 쓰는 것이 getter.
Setter
자바스크립트에서 setter는 특정한 속성에 값이 변경될 때마다 함수를 실행하는데 사용될 수 있습니다.
set fullName(value) { ///<- 할당하는 값을 받아올 수 있다. value
console.log(value)
};
student.fullName = “김철수” ; // 이 할당하는 행동이 있을 때 console.log “김철수” 나옴.
별도로 함수를 호출하는 명령어를 쓰지 않아도 set으로 지정해둔 함수가 호출되는 것.
ex) 0이하의 숫자가 입력되면 그냥 0으로 입력될 수 있도록 한다 : set
Extends!
확장. 상속.
예시
class Square extends Polygon {
constructor(length) {
super(length, length);
this.name = 'Square';
}
get area() {
return this.height * this.width;
}
set area(value) {
this.area = value;
}
}
super라는 것은 부모를 뜻한다고 보면된다. this가 인스턴스를 뜻하듯이.
자식요소에서 constructor 를 추가하는 순간, Animal을 만들때 필요했던 매개변수들도 다 받아와야 한다.
class Animal {
constructor(color) {
this.color = color;
}
eat() {
console.log(“eat!”)
}
};
class Tiger extends Animal {}
const tiger = new Tiger(‘노랑이’)
tiger.eat() ; => eat!
class Dog extends Animal { //추가할 부분이 있으면 이렇게 추가하면 된다.
play() {
console.log(“play!”)
}
class dog = new Dog;
dog.play(); /// play !
class Dog extends Animal {
constructor(color, ownerName) {
super(color); // 부모클래스의 생성자의 color를 전달해주는 것. 인자 두개면 super(color, age)
this.ownerName = ownerName;
play() {
console.log(“play!”)
}
const dog = new Dog (“빨강이”, “엘리”);
**오버라이딩. 자식클래스에서 부모클래스의 값 위에 덮어 씌운다.
부모의 기능을 유지하면서, 추가적인것을 하고 싶다면
eat() {
super.eat(); // 부모에 있는 eat을 호출한 뒤에,
console.log(‘강아지가 먹는다’); // 자식의 eat을 오버라이딩 하는거.
}
정리.
- 인스턴스 레벨에 들어갈 데이터인가? 클래스 레벨에 들어갈 데이터인가? => static 사용여부
(즉 새로 인스턴스를 만들어 낼 때마다 변화하는 데이터인가? 아니면 동일하게 참조되는 데이터인가? (새로 만들어진 인스턴스의 데이터
- 외부에서 접근하지(수정하지) 말아야 할 데이터가 있는가? => #을 붙일지 말지. this.#name // #display() {}
- getter, setter를 통해 변수에 접근할 때마다 혹은 변수를 수정할 때마다 함수를 실행하게 하는 내용이 필요한지.
- 상속을 통해 효율적으로 객체들을 만들 수 있는가?
- 클래스 정리 샘플
https://googlechrome.github.io/samples/classes-es6/index.html