호이스팅이 아예 일어나지 않는 것이 아니라, var가 아닌 let과 const처럼 호이스팅됨.
클래스를 먼저 선언하지 않으면 ReferenceError 발생
class 표현식
// 클래스 이름이 없는 표현식
let ToggleStudy = class {
constructor(boss, member) {
this.boss = boss;
this.member = member;
}
}
console.log(ToggleStudy.name) // ToggleStudy
// 클래스 이름이 있는 표현식
let ToggleStudy = class ToggleStudy2 {
constructor(boss, member) {
this.boss = boss;
this.member = member;
}
sayHi() {
console.log(ToggleStudy2)
}
}
console.log(ToggleStudy.name) // ToggleStudy2
Class 표현식은 이름을 가질 수도 있고, 가지지 않을 수도 있음.
클래스 표현식에 붙인 이름은 오직 클래스 내부에서만 사용 가능
클래스가 할당된 변수를 사용해 클래스를 생성하지 않고, 기명클래스 이름을 사용해 클래스를 생성하면 에러가 발생함.
4. 클래스 동작 원리
class Study {
// 생성자
constructor(name) {
this.name = name;
}
sayName() {
console.log(this.name)
}
}
// 인스턴스 생성
const toggleStudy = new Study('toggle')
toggleStudy.sayName(); // toggle
console.log(toggleStudy instanceof Study) // true
클래스를 만들고 new Study()를 호출하는 순간 내부에 정의한 메서드가 들어있는 객체(인스턴스)가 생성됨.
new를 하는 순간 constructor()가 자동 호출되므로 특별한 절차없이 객체를 초기화할 수 있음.
이때 constructor 내부에서 선언한 클래스 필드는 인스턴스를 가리키는 this에 바인딩이 됨.
이후 toggleStudy.sayName()과 같이 클래스의 인스턴스를 통해 클래스 외부에서 언제나 참조 가능한 상태가 됨.
클래스 내부에서 정의한 메서드는 Study.prototype에 저장되는 것
객체의 메서드를 호출하면, 함수의 prototype에서 메서드를 가져옴.
5. 정적 메서드(static)
정적 메서드는 클래스의 인스턴스가 아닌 클래스 이름으로 호출하며, 인스턴스를 생성하지 않아도 호출 가능함.
prototype이 아닌 클래스 함수 자체에 메서드를 설정하는 것
특정 클래스 인스턴스가 아닌 클래스 '전체’에 필요한 기능을 만들 때 사용할 수 있음.
class Study {
constructor(name) {
this.name = name;
}
static sayHi() {
console.log("hi")
}
}
Study.sayHi(); // hi
const study = new Study()
study.sayHi() // Uncaught TypeError: study.sayHi is not a function
- 정적 메서드는 this를 사용할 수 없고, 정적 메서드 내부에서의 this는 클래스 인스턴스가 아닌 클래스 자신을 가리킴.
- 정적 메서드에서 this를 사용할 수 없다는 뜻은 메서드 내부에서 this를 사용할 필요가 없는 메서드는 정적 메서드로 만들 수 있다는 의미
- 애플리케이션 전역에서 사용할 유틸 함수를 생성할 때 자주 사용됨.
- 유틸리티 클래스는 상태를 관리하지 않는 클래스라고 볼 수 있음.
- Math 객체의 메서드도 static 메서드의 형식`Math.max() Math.min()`
- 어떤 메서드를 사용해야 할 때, 해당 메서드가 인스턴스의 변수를 사용하지 않고, 인스턴스가 생성되지 않았더라도 사용해야 한다면 정적 메서드를 사용하면 됨.
### 6. Getter와 Setter
#### getter(획득자)
- 클래스 필드에 접근할 때마다 클래스 필드의 값을 조작하는 행위가 필요한 경우 사용
- 메서드 이름 앞에 get 키워드를 붙여서 정의
- getter는 반드시 return 반환값이 필요
let user = {
name: "John",
surname: "Smith",
get fullName() {
return ${this.name} ${this.surname};
}
};
alert(user.fullName); // John Smith
- 일반 프로퍼티에서 값에 접근하는 것처럼 평범하게 user.fullName을 사용해 프로퍼티 값을 얻을 수 있음.
- 위의 코드에는 setter가 없기 때문에 user.fullName = "something"으로 값을 할당하려고 하면 에러가 발생함.
#### setter(설정자)
- 클래스 필드에 값을 할당할 때마다 클래스 필드의 값을 조작하는 행위가 필요한 경우 사용
- 메서드 이름 앞에 set 키워드를 붙여서 정의
let user = {
name: "John",
surname: "Smith",
get fullName() {
return ${this.name} ${this.surname};
},
set fullName(value) {
[this.name, this.surname] = value.split(" ");
}
};
// 주어진 값을 사용해 set fullName이 실행됨.
user.fullName = "Alice Cooper";
alert(user.name); // Alice
alert(user.surname); // Cooper
-----
# 팩토리
### 1. 팩토리란?
- 객체를 반환하는 함수
- 자바스크립트에서는 모든 함수가 객체를 리턴할 수 있는데, 그중에서도 new 키워드가 없는 경우를 팩토리 함수라고 볼 수 있음.
- 클래스와 new 키워드의 복잡함 없이 객체 인스턴스를 쉽게 생성 할 수 있음. (필요하지는 않지만, new 키워드를 사용해도 무방)
- 팩토리 함수명에는 create 접두사를 붙여서 명확한 의도를 전달할 수 있다. `createJelly(){}`
- jelly와 iceCream 팩토리로 생성된 객체를 반환하는 dessert 팩토리 함수를 만들 수 있음.
# 클래스 vs 팩토리
- 둘 다 객체를 생성하는 함수
- 캡슐화(내부 변수, 감추고 싶은 함수에 접근 가능한가)
- 클래스 : 캡슐화 불가능
- 팩토리 : 캡슐화 가능
- 불변성(한 번 정의된 함수가 변경되는가)
- 클래스 : 변경 가능
- 팩토리 : 변경 불가
- 메모리 소비
- 클래스 : 메서드는 프로토타입 객체에서 한 번만 생성되어 모든 인스턴스에서 공유되기 때문에 팩토리에 비해 우수함.
- 팩토리 : 수천 개의 동일한 객체를 만들 경우 클래스보다 메모리 비용이 많이 듦.
---
### 출처
- 클래스
https://corock.tistory.com/472
https://ko.javascript.info/class
https://ko.javascript.info/static-properties-methods
https://mygumi.tistory.com/253
https://ko.javascript.info/property-accessors
- 팩토리
https://ui.toast.com/weekly-pick/ko_20160905
https://tpgns.github.io/2018/04/08/javaScript-factory-function-with-es6/#fnref1
https://velog.io/@godori/factory-method-pattern
- 클래스 vs 팩토리
https://simsimjae.tistory.com/373
https://steemit.com/kr/@wonsama/javascript-class-vs-factory
- 스트릭트 모드
https://beomy.tistory.com/13
클래스
1. 클래스란?
클래스는 항상 엄격 모드(use strict)로 실행됨.
2. 클래스의 구조
Class body
constructor나 메서드와 같은 class 멤버를 정의하는 곳
constructor(생성자)
3. class 표현식과 class 선언
class 선언
class 표현식
4. 클래스 동작 원리
5. 정적 메서드(static)
특정 클래스 인스턴스가 아닌 클래스 '전체’에 필요한 기능을 만들 때 사용할 수 있음.
Study.sayHi(); // hi
const study = new Study() study.sayHi() // Uncaught TypeError: study.sayHi is not a function
let user = { name: "John", surname: "Smith",
get fullName() { return
${this.name} ${this.surname}
; } };alert(user.fullName); // John Smith
let user = { name: "John", surname: "Smith",
get fullName() { return
${this.name} ${this.surname}
; },set fullName(value) { [this.name, this.surname] = value.split(" "); } };
// 주어진 값을 사용해 set fullName이 실행됨. user.fullName = "Alice Cooper";
alert(user.name); // Alice alert(user.surname); // Cooper
function createDessert() { return { type: 'dessert', bowl: [ createJelly(), createIceCream() ] }; }