reference
https://ko.javascript.info/static-properties-methods
prototype
이 아닌 클래스 함수 자체에 메서드를 설정할 수 있다
이런 메서드를 정적(static) 메서드라고 부른다
class Person {
static staticMethod() {
console.log("static");
}
}
Person.staticMethod(); // static
정적 메서드는 메서드를 프로퍼티 형태로 직접 할당하는 것과 동일한 일을 한다
class Person { }
Person.staticMethod = function() {
console.log("static");
}
Person.staticMethod(); // static
Person.staticMethod()
가 호출될 때 this
의 값은 클래스 생성자인 User
자체가 된다 (점 앞 객체)
정적 메서드는 어떤 특정한 객체가 아닌 클래스에 속한 함수를 구현할 때 주로 사용된다
class Posting {
constructor(title, date) {
this.title = title;
this.date = date;
}
static compareDate(postingA, postingB) {
return postingA.date - postingB.date;
}
}
let postings = [
new Posting("정적 메서드", new Date(2022, 12, 22)),
new Posting("은닉화", new Date(2022, 11, 28)),
new Posting("객체지향", new Date(2022, 05, 10)),
];
posting.sort(Posting.compareDate);
conole.log(postins[0].title); // 객체지향
Posting.compareDate
는 posting을 비교해주는 수단으로 글 전체를 위에서 바로보며 비교를 수행한다
Posting.compareDate
는 글 하나의 메서드가 아닌 클래스의 메서드여야 하는 이유이다
팩토리 메서드를 구현한 코드이다
class Posting {
constructor(title, date) {
this.title = title;
this.date = date;
}
static createToday() {
// this는 Posting이다
return new this("Monday", new Date());
}
}
let posting = Posting.createToday();
console.log(posting.title); // Monday
이제 Monday라는 문자가 필요할 때마다 Posting.createToday()
를 호출하면 된다
여기서도 마찬가지로 Posting.createToday()
는 posting 메서드가 아닌 전체 클래스의 메서드이다
정적 메서드는 항목 검색, 저장, 삭제, 수정 등 데이터 베이스 관련 클래스에서도 사용할 수 있다
Posting.remove({ id: 1001 })
정적 프로퍼티도 일반 클래스 프로퍼티와 유사하게 앞에 static이 붙는다
class Posting {
static postA = "함수형 프로그래밍";
}
console.log(Posting.postA); // 함수형 프로그래밍
Posting
에 프로퍼티를 직접 할당하는 것과 동일하게 동작한다
Posting.postA = "함수형 프로그래밍";
정적 프로퍼티와 메서드는 상속이된다
class Human {
static korean = "한국인";
constructor(name, speed) {
this.name = name;
this.speed = speed;
}
run(speed = 0) {
this.speed += speed;
console.log(`${this.name}이 ${this.speed}속도로 달린다`);
}
static compare(humanA, humanB) {
return humanA.speed - humanB.speed;
}
}
class SoccerPlayer extends Human {
goal() {
console.log(`${this.name}이 골을 넣었습니다!`);
}
}
let soccerPlayer = [
new SoccerPlayer("손흥민", 30);
new SoccerPlayer("케인", 25);
];
soccerPlayer.sort(SoccerPlayer.compare);
soccerPlayer[0].run(); // 케인이 25속도로 달린다
console.log(SoccerPlayer.korean); // 한국인
SoccerPlayer.compare
를 호출하면 Human.compare
가 호출된다
이게 가능한 이유는 extend
키워드는 SoccerPlayer
의 [[Prototype]]
이 Human
을 참조하게 해준다
따라서 SoccerPlay extends Human
은 두개의 [[Prototype]]
참조를 만들어낸다
SoccerPlayer
는 포로토타입을 통해 함수 Human
을 상속받는다SoccerPlayer.prototype
은 프로토타입을 통해 Human.prototype
을 상속받는다이런 과정이 있기 때문에 일반 메서드 상속과 정적 메서드 상속이 가능하다
class Human {}
class SoccerPlayer extends Human {}
// 정적 메서드
console.log(SoccerPlayer.__proto__ === Human); // true
// 일반 메서드
console.log(SoccerPlayer.__proto__ === Human.prototype); // true
정적 메서드는 특정 클래스 인스턴스가 아닌 클래스 전체에 필요한 기능을 만들 때 사용할 수 있다
인스턴스끼리 비교해주는 메서드 Posting.compareDate(postingA, postingB)
이나 팩토리 메서드 Posting.createToday()
를 만들 때 정적 메서드가 쓰인다
정적 메서드는 클래스 선언부 안에 위차하고 앞에 static
이라는 키워드가 붙는다
정적 프로퍼티는 데이터를 클래스 수준에 저장하고 싶을 때 사용한다
정적 프로퍼티 역시 개별 인스턴에 묶이지 않는다
class Class {
static property = "property";
static method() {
}
}
// 위와 같다
Class.property = "property"'
Class.method = function() { }
정적 프로퍼티와 정적 메서드는 상속이 가능하다
class B extends A
는 클래스 B의 프로토타입이 클래스 A
를 가리키게 한다 (B.[[Prototype]] = A
)
따라서 B
가 원하는 프로퍼티나 메서드를 찾지 못하면 A
로 검색이 이어진다
객체는 보통 Object.prototype
을 상솓받고 hasOwnProperty
같은 일반 객체 메서드에 접근할 수 있다
class Human {
consturctor(name) {
this.name = name;
}
}
let human = new Human("Son");
// 메서드 hasOwnPropertysms Object.protoype에서 왔다
console.log(human.hasOwnProperty("name")); // true
만약 Object를 상속받는다면?
class Human extends Object {
consturctor(name) {
this.name = name;
}
}
let human = new Human("Son");
console.log(human.hasOwnProperty("name")); // Error
에러를 해결해보면
상속받는 클래스는 생성자 super()
를 반드시 호출해야 한다
그렇지 않으면 this
가 정의되지 않는다
class Human extends Object {
consturctor(name) {
super();
this.name = name;
}
}
let human = new Human("Son");
console.log(human.hasOwnProperty("name")); // true
아직 class Human extends Object
와 class Human
은 다른점이 있다
extends
문법은 두개의 프로토타입을 설정한다
prorotype
사이 (일반 메서드용)class Human extends Object
는 다음과 같은 관계를 만든다
class Human extends Object {}
console.log(Human.prototype.__proto__ === Object.prototype) // true
console.log(Human.__proto__ === Object); // true
따라서 Human
은 Object
의 정적 메서드에 접근할 수 있다
class Human extends Object {}
// 보통은 Object.getOwnPrototypeNames 로 호출한다
console.log(Human.getOwnPrototypeNames({a: 1, b: 2})); // a, b
그러나 extends Object
가 없으면 Human.__proto__
는 Object
로 설정되지 않는다
class Human {}
console.log(Human.prototype.__proto__ === Object.prototype) // true
console.log(Human.__proto__ === Object); // false
console.log(Human.__proto__ === Function.prototype) // true (모든 함수의 기본 프로토타입)
console.log(Human.getOwnPrototypeNames({ a: 1, b: 2 })); // Error
이런 이유로 Human
에서 Object
의 정적 메서드를 사용할 수 없다
한편 Function.prototype
은 call, apply, bind
등 일반 함수 메서드를 가진다
내장 객체, Object
의 생성자는 Object.__proto === Function.prototype
관계를 갖기 때문에 Function.prototype
에 정의된 함수 메서드는 두 경우 모두 사용할 수 있다