Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

25. 클래스 #131

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions 9주차 (25장)/25. 클래스/LSH0125/example.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// super 키워드 활용

class Base {
constructor(a, b) {
this.a = a;
this.b = b;
}

saySum () {
return this.a + this.b ;
}
}

class Derived extends Base {
constructor(a, b, c) {
// super의 호출, 수퍼클래스의 constructor를 호출한다.
super(a, b);
this.c = c
}

saySum () {
// super의 참조, 수퍼클래스의 메서드를 호출한다.
return super.saySum() + this.c;
}
}

const derived = new Derived(1, 2, 3);
console.log(derived.saySum()); // 6
79 changes: 79 additions & 0 deletions 9주차 (25장)/25. 클래스/LSH0125/기억에 남는 내용.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# ✏️ 기억에 남는 내용

## **클래스란?**
---
### **프로토타입의 문법적 설탕?**
클래스는 일종의 함수이며 기존 프로토타입 기반 패턴을 클래스 기반 패턴처럼 사용할 수 있도록 하는 `문법적 설탕`이라고 볼 수도 있지만, 생성자 함수와 정확히 동일하게 동작하지는 않는다.
- 클래스를 프로토타입 기반 객체 생성 패턴의 단순한 문법적 설탕이라고 보기보다는 '새로운 객체 생성 메커니즘'으로 보는 것이 좀 더 합당하다. (인스턴스를 생성하는 것이 유일한 존재 이유)

## **클래스 정의**
---
`class` 키워드를 사용하여 정의(일반적)하거나 표현식으로 정의할 수 있다. 따라서 클래스는 값으로 사용할 수 있는 일급 객체이다.
- 클래스의 몸체에는 0개 이상의 '메서드만' 정의할 수 있다.

### **클래스 호이스팅**
클래스 선언문도 변수 선언, 함수 정의와 마찬가지로 호이스팅이 발생하지만 let, const 키워드로 선언한 변수처럼 호이스팅된다. (호이스팅이 발생하지 않는 것처럼 동작)

## **클래스의 메서드**
---
클래스 몸체에서 정의할 수 있는 메서드는 constructor(생성자), 프로토타입 메서드, 정적 메서드가 있다.
### **constructor**
인스턴스를 생성하고 초기화하기 위한 특수한 메서드다.(이름 변경 금지)
### **프로토타입 메서드**
생성자 함수에 의한 객체 생성 방식과는 달리 명시적으로 프로포타입에 메서드를 추가하지 않아도 기본적으로 프로토타입 메서드가 된다.
### **정적 메서드**
인스턴스를 생성하지 않아도 호출할 수 있는 메서드로, 메서드에 `static` 키워드를 붙이면 된다.

### **정적 메서드 vs 프로토타입 메서드**
1. 속해 있는 프로토타입 체인이 다르다.
2. 그러므로 정적 메서도는 클래스로 호출하고, 프로토타입 메서드는 인스턴스로 호출한다.
3. 정적 메서드는 인스턴스 프로퍼티를 참조할 수 없지만 프로토타입 메서드는 인스턴스 프로퍼티를 참조할 수 있다.

```JS
class Person {
constructor(name) {
this.name = name;
}

sayHi() {
console.log('Hi! My name is ${this.name}');
}

static sayHello() {
console.log('Hello');
}
}

const me = new Person('Lee');

console.log(me.name);
// 프로토타입 메서드 호출
me.sayHi();
// 정적 메서드 호출
Person.sayHello();
```

## **프로퍼티**
---
### **인스턴스 프로퍼티**
constructor 내부에서 정의하여 클래스가 생성한 인스턴스의 프로퍼티가 된다.
### **접근자 프로퍼티**
접근자 함수(데이터 프로퍼티의 값을 읽거나 저장할 때 사용, getter 함수와 setter 함수)로 구성된 프로퍼티로,
### **클래스 필드 정의 제안**
'클래스 필드'란 클래스 기반 객체지향 언어에서 클래스가 생성할 인스턴스의 프로퍼티를 가리키는 용어다.
- '자바스크립트'의 클래스에서는 인스턴스 프로퍼티의 선언과 초기화는 반드시 constructor 내부에서, this에 프로퍼티를 추가해야한다.
- 하지만 '자바'의 클래스에서는 클래스 필드를 마치 변수처럼 클래스 몸체에 this 없이 선언하고, 클래스 필드를 참조할 때에도 this 없이 참조할 수 있다.
- 캡슐화를 완전하게 지원하지 않고 접근 제한자를 지원하지 않는 자바스크립트의 단점을 보완하고자 `private 필드 정의` 제안, 정적 필드를 정의하기 위해 `static 필드 정의` 제안

## 상속에 의한 클래스 확장
---
상속에 의한 클래스 확장은 기존 클래스를 상속 받아 새로운 클래스를 확장하여 정의하는 것이다.
- 기존 클래스의 속성을 그대로 사용하고 자신만의 고유한 속성을 추가하여 확장한다. 코드 재사용 관점에서 매우 유용하다.

### **`extends` 키워드**
상속을 통해 클래스를 확장할 때 사용하는 키워드이다. ***수퍼클래스*** (상속된 클래스, 베이스 클래스, 부모 클래스)와 ***서브클래스*** (상속을 통해 확장된 클래스, 파생 클래스, 자식 클래스) 간의 상속 관계를 설정한다.
- `extends` 키워드 다음에는 클래스뿐만이 아니라 함수 객체로 평가될 수 있는 모든 표현식을 사용할 수 있다. 이를 통해 동적으로 상속받을 대상을 결정할 수 있다. (`extends` 키워드)
- 따라서 String, Number, Array 같은 표준 빌트인 객체도 `extends` 키워드를 사용하여 확장할 수 있다.

### **`super` 키워드**
super은 함수처럼 호출할 수도, 식별자처럼 참조할 수도 있는 키워드이다. 호출할 경우 '수퍼클래스의 constructor'을 호출하고, 참조할 경우 '수퍼클래스의 메서드'를 호출한다. (활용은 예제코드 참고)
18 changes: 18 additions & 0 deletions 9주차 (25장)/25. 클래스/LSH0125/퀴즈.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# 📝 간단한 퀴즈

1. 클래스 몸체에서 정의할 수 있는 메서드 3종류를 쓰고 간단히 정리해보자.
2. 클래스를 확장할 때의 '상속'과 프로토타입 기반의 '상속'의 차이는 무엇인지 간단히 정리해보자.
3. 다음 코드에서 서브 클래스와 수퍼 클래스 두 쌍을 찾아보자.
```JS
class Base {}
class Derived extends Base {}

class MyArray extends Array {
uniq() {
return this.filter((v, i, self) => self.indexOf(v) === i);
}
average() {
return this.reduce((pre, cur) => pre + cur, 0) / this.length;
}
}
```