- Published on
2024.07.06
[딥다이브] - 25. 클래스(2)
25.6. 클래스의 인스턴스 생성 과정
- 인스턴스 생성과 this 바인딩
new 연산자와 함께 클래스를 호출하면 constructor의 내부 코드가 실행되기 전 암묵적으로 빈 객체(인스턴스)가 생성되고, 프로토타입으로 클래스의 prototype 프로퍼티가 가리키는 객체가 설정된다. 이후, 인스턴스가 this에 바인딩된다.
- 인스턴스 초기화
constructor 내부 코드가 실행되어 this에 바인딩되어 있는 인스턴스를 초기화한다. constructor가 생략되었다면 이 과정도 생략된다.
- 인스턴스 반환
클래스의 모든 처리가 끝나면 인스턴스가 바인딩된 this가 암묵적으로 리턴된다.
class Person {
// 생성자
constructor(name) {
// 1. 암묵적으로 인스턴스가 생성되고 this에 바인딩된다.
console.log(this) // Person {}
console.log(Object.getPrototypeOf(this) === Person.prototype) // true
// 2. this에 바인딩되어 있는 인스턴스를 초기화한다.
this.name = name
// 3. 완성된 인스턴스가 바인딩된 this가 암묵적으로 리턴된다.
}
}
25.7. 프로퍼티
25.7.1. 인스턴스 프로퍼티
class Person {
constructor(name) {
//인스턴스 프로퍼티
this.name = name
}
}
const me = new Person('Lee')
console.log(me) // Person {name: "Lee"}
인스턴스 프로퍼티는 constructor 내부에서 정의해야 한다. constructor 내부에서 this에 인스턴스 프로퍼티를 추가해, 암묵적으로 생성한 빈 객체인 인스턴스가 초기화된다. constructor 내부에서 this에 추가한 프로퍼티는 언제나 클래스가 생성한 인스턴스의 프로퍼티가 된다.
25.7.2. 접근자 프로퍼티
접근자 프로퍼티는 자체적으로는 값([[Value]]
)를 갖지 않고 다른 데이터 프로퍼티의 값을 읽거나 저장할 때 사용하는 접근자 함수(getter
/setter
함수)로 구성된 프로퍼티다. 접근자 프로퍼티는 클래스에서도 사용할 수 있다.
class Person {
constructor(firstName, lastName) {
this.firstName = firstName
this.lastName = lastName
}
// fullName은 접근자 함수로 구성된 접근자 프로퍼티다.
// getter 함수
get fullName() {
return `${this.firstName} ${this.lastName}`
}
// setter 함수
set fullName(name) {
;[this.firstName, this.lastName] = name.split(' ')
}
const me = new Person('Seungho', 'Han')
me.fullName = 'SH Han'
console.log(me.fullName) // SH Han
}
25.7.3. 클래스 필드 정의 제안
클래스 필드: 클래스 기반 객체지향 언어에서 클래스가 생성할 인스턴스의 프로퍼티
자바의 클래스 필드는 클래스 내부에서 변수처럼 사용된다. 자바스크립트는 constructor 내부에서 this에 프로퍼티를 추가하지만, 자바는 변수처럼 클래스 몸체에 this 없이 선언한다.
차이점이 있지만, 최신 브라우저/Node.js 환경에서는 자바스크립트도 클래스 기반 객체지향 언어의 클래스 필드처럼 정의할 수 있는 클래스 필드 정의 제안이 ECMAscript에 정식 표준 사양으로 채택되었다.
class Person {
// 클래스 필드 정의
name = 'lee'
// ③
age;
// ①
this.name = ''; // SyntaxError: Unexpected token '.'
constructor(age) {
console.log(job) // ② ReferenceError: job is not defined
// ④ 클래스 필드 초기화
this.age = age;
}
}
const me = new Person('30')
console.log(me) // Person { name: 'lee', age: '30' }
①. this는 클래스의 constructor와 메서드 내에서만 유효하므로 this에 클래스 필드를 바인딩해서는 안 된다.
②. 자바스크립트는 클래스 필드를 참조하는 경우 반드시 this를 사용해야 한다.
③. 초기값을 할당하지 않으면 undefined
를 갖는다. ④. 외부의 초기값으로 클래스 필드를 초기화해야 할 필요가 있다면 constructor에서 클래스 필드를 초기화한다.
25.7.4. private 필드 정의 제안
자바스크립트는 다른 클래스 기반 객체지향 언어들처럼 접근 제한자를 지원하지 않아 클래스 필드는 기본적으로 public해 외부에 노출된다. 현재는 private 필드를 정의할 수 있는 표준 사양이 적용되어 있다.
private 필드의 선두에 #을 붙여준다. private 필드를 참조할 때도 #을 붙여야 한다. private 필드는 클래스 내부에서만 참조할 수 있다. 또한, 클래스 몸체에서 정의해야하며 constructor에 정의하면 에러가 발생한다.
class Person {
// private 필드 정의
#name = ''
constructor(name) {
// private 필드 참조
this.#name = name
}
}
const me = new Person('Lee')
// private 필드 #name은 클래스 외부에서 참조 불가
console.log(me.#name) // SyntaxError
접근 가능성 | public | private |
---|---|---|
클래스 내부 | O | O |
자식 클래스 내부 | O | X |
클래스 인스턴스를 통한 접근 | O | X |
25.7.5. static 필드 정의 제안
클래스는 정적 메서드와 달리 정적 필드는 static
키워드로 정의할 수 없었다. 그러나 새 표준 사양인 "Static class featurs"를 통해 static public 필드
, static private 필드
, static private 메서드
가 제안되었고, 이 중 static public/private
은 최신 브라우저/Node.js에 구현되어 있다.
class MyMath {
// static public 필드 정의
static PI = 22 / 7;
// static private 필드 정의
static #num = 10;
// static 메서드
static increment() {
return ++MyMath.#num;
}
console.log(MyMath.PI) // 3.142857142857143
console.log(MyMath.increment()) // 11
}