6) 클래스의 인스턴스 생성 과정
1. 인스턴스 생성과 this 바인딩
- 클래스 호출 시 암묵적으로 빈 객체가 생성되는데, 이것이 클래스가 생성한 인스턴스임
- 인스턴스의 프로토타입으로 prototype 프로퍼티가 가리키는 객체가 설정됨
- 인스턴스는 this에 바인딩(constructor 내부의 this는 클래스가 생성한 인스턴스를 가리킴)
2. 인스턴스 초기화
- constructor가 인수로 전달받은 초기값으로 this에 바인딩된 인스턴스의 프로퍼티 값을 초기화
- constructor 생략 시 이 과정도 생략됨
3. 인스턴스 반환
- 완성된 인스턴스가 바인딩된 this가 암묵적으로 반환됨
7) 프로퍼티
1. 인스턴스 프로퍼티
- 인스턴스 프로퍼티는 contructor 내부에서 정의해야 함
- this에 추가한 이 때의 프로퍼티는 언제나 클래스가 생성한 인스턴스의 프로퍼티이며, 언제나 public함
2. 접근자 프로퍼티
- 접근자 함수로 구성된 프로퍼티
- getter, setter 함수로 구성되며 이들 이름은 인스턴스 프로퍼티처럼 사용됨
- getter는 반드시 무언가를 반환해야 하며, setter는 반드시 매개변수(단 하나의 매개변수만 선언 가능)가 있어야 함
- 클래스의 접근자 프로퍼티는 프로토타입의 프로퍼티가 됨
3. 클래스 필드 정의 제안
- 클래스 기반 객체지향 언어에서 클래스가 생성할 인스턴스의 프로퍼티를 클래스 필드라 함
- 최신 브라우저(Chrome 72 이상) 또는 최신 Node.js(버전 12 이상)에서는 클래스 몸체에 클래스 필드 선언이 가능("클래스 필드 정의"가 새롭게 제안되었음)
- 이 경우 this에 클래스 필드 바인딩 불가(this는 클래스의 constructor, 메서드 내에서만 유효)
- 클래스 필드 참조 시 this 반드시 사용
- 클래스 필드에 초기값이 없으면 undefined 반환
- 외부 초기값으로 초기화를 해야하는 경우 constructor에서 클래스 필드 초기화 필요
- 함수 또한 클래스 필드에 할당이 가능하여 이를 통해 메서드 정의도 가능(인스턴스 메서드가 되므로 권장하지 않음)
class Person {
// 클래스 몸체에 클래스 필드 정의하기
name = 'Lee';
}
const me = new Person();
console.log(me); // Person {name: "Lee"}
4. private 필드 정의 제안
- 최신 브라우저(Chrome 72 이상) 또는 최신 Node.js(버전 12 이상)에서 private 필드 정의가 새롭게 제안됨
- private 필드의 선두에 #을 붙이며, 참조할 때에도 #를 붙임
- 단, 클래스 내부에서만 참조 가능
- private 필드 접근은 접근자 프로퍼티를 통해 간접적으로 접근하는 방법만 가능
- 반드시 클래스 몸체에 정의할 것
class Person {
#name = '';
constructor(name) {
this.#name = name;
}
}
5. static 필드 정의 제안
- 최신 브라우저(Chrome 72 이상) 또는 최신 Node.js(버전 12 이상)에서 "Static class features"가 새롭게 제안됨
- static 키워드 사용
class MyMath {
static PI = 22 / 7;
static #num = 10;
static increment() {
return ++MyMath.#num;
}
}
8) 상속에 의한 클래스 확장
1. 클래스 상속과 생성자 함수 상속
- 상속에 의한 클래스 확장은 기존 클래스를 상속받아, 새로운 클래스를 확장하여 정의하는 것
- 코드 재사용 관점에서 매우 유용함
- extends 키워드 사용(기본 제공됨)
2. extends 키워드
- extends 키워드를 사용하여 상속받을 클래스를 정의
- 상속을 통해 확장된 클래스를 서브(파생/자식) 클래스, 서브클래스에게 상속된 클래스를 수퍼(베이스/부모) 클래스라 함
// 수퍼(베이스/부모) 클래스
class Base ()
// 서브(파생/자식) 클래스
class Derived extends Base {}
3. 동적 상속
- extends 키워드를 통해 클래스 뿐만 아니라 생성자 함수를 상속받아 클래스 확장도 가능
- extends 키워드 앞에는 반드시 클래스가 올 것
- extends 키워드 다음에는 모든 표현식 사용 가능(동적으로 상속받을 대상 결정)
4. 서브클래스의 constructor
- 서브클래스에서 constructor 생략 시 아래와 같은 constructor가 암묵적으로 정의됨
- args는 클래스 호출 시 전달된 인수 리스트를, super()는 수퍼 클래스의 contructor를 호출하여 인스턴스를 생성
constructor(...args) { super(...args); }
5. super 키워드
1) 함수처럼 호출 시 수퍼클래스의 constructor를 호출
- 주의사항 : 서브클래스에서 constructor를 생략하지 않으면 반드시 super 호출해야 함, super 호출 전에는 this 참조 불가, 서브클래스의 constructor에서만 호출이 가능
2) 식별자처럼 참조 시 수퍼클래스의 메서드를 호출
- super 참조가 동작하기 위해서는 super를 참조하고 있는 메서드가 바인딩되어 있는 객체의 프로토타입을 찾을 수 있어야 하는데, 이를 위해 메서드는 내부 슬롯 [[HomeObject]]를 가지며, 이는 자신을 바인딩하고 있는 객체를 가리킴(ES6의 메서드 축약 표현으로 정의된 함수만이 [[HomeObject]]를 가짐
6. 표준 빌트인 생성자 함수 확장
- String, Number, Array 등의 표준 빌트인 객체도 extends 키워드를 통해 확장이 가능
26. ES6 함수의 추가 기능
1) 함수의 구분
- 자바스크립트의 함수(ES6 이전의 함수)는 별다른 구분 없이 다양한 목적으로 사용되는데, 이는 실수를 유발시킬 수 있으며 성능 면에서도 손해임
- ES6에서는 사용 목적에 따라 함수를 세 가지 종류로 구분
- 일반 함수와 달리, 메서드와 화살표 함수는 ES6 이전의 함수와 명확한 차이를 가짐
ES6 함수의 구분 | constructor | prototype | super | arguments |
일반 함수(Normal) | O | O | X | O |
메서드(Method) | X | X | O | O |
화살표 함수(Arrow) | X | X | X | X |
2) 메서드
- ES6 사양에서 메서드는 메서드 축약 표현으로 정의된 함수만을 의미함
- 이는 인스턴스를 생성할 수 없는 non-constructor임
- prototype 프로퍼티가 없고 프로토타입도 생성하지 않음
- 자신을 바인딩한 객체를 가리키는 내부 슬롯 [[HomeObject]]를 가지므로 super 키워드 사용 가능
const obj = {
x: 1,
foo() { return this.x; };, // 메서드
bar: function() { return this.x }; // 메서드가 아닌 일반 함수
}
3) 화살표 함수
- function 키워드 대신 화살표( => )를 사용하여 간략하게 함수를 정의함
- 내부 동작도 기존의 함수보다 간략함
- 콜백 함수 내부에서 this가 전역 객체를 가리키는 문제를 해결
1. 화살표 함수 정의
- 함수 표현식으로 정의해야 함
- 매개변수가 여러 개면 소괄호 () 안에 매개변수 선언
- 매개변수가 한 개인 경우 소괄호 () 생략 가능(단, 매개변수가 없으면 생략 불가)
- 함수 몸체가 하나의 문으로 구성된다면 중괄호 {} 생략 가능(단, 표현식이 아닌 문은 생략 불가)
- 객체 리터럴을 반환하는 경우는 객체 리터럴을 소괄호 ()로 감싸야 함
- 화살표 함수도 즉시 실행 함수로 사용 가능
- 고차 함수에 인수로 전달 가능
const power = x => x ** 2; // 중괄호 생략
const create = (id, content) => ({ id, content }); // 객체 리터럴 감쌈
2. 화살표 함수와 일반 함수의 차이
- 화살표 함수는 인스턴스를 생성할 수 없는 non-constructor임
- 중복된 매개변수 이름을 선언할 수 없음
- 함수 자체의 this, arguments, super, new.targer 바인딩을 갖지 않음
3. this
- 화살표 함수 내부에서 this 참조 시 언제나 상위 스코프의 this를 참조하는 lexical this 나타남
- 메서드를 정의하는 것은 ES6 메서드 축약 표현으로 정의한 ES6 메서드 사용 권장
- 프로퍼티 동적 추가시에는 일반 함수를 할당할 것(ES6 메서드를 통해 동적 추가하려면, 객체 리터럴을 바인딩하고 프로토타입의 constructor 프로퍼티와 생성자 함수간의 연결을 재설정)
- 클래스 필드에 할당한 화살표 함수는 인스턴스 메서드가 되므로, 역시 메서드를 정의하는 것은 ES6 메서드 축약 표현으로 정의한 ES6 메서드 사용 권장
4. super
- 화살표 함수 내부에서 super 참조 시 상위 스코프의 super를 참조함
5. arguments
- 화살표 함수 내부에서 arguments 참조 시 상위 스코프의 arguments를 참조함
- 화살표 함수로 가변 인자 함수를 구현해야 하는 경우 반드시 Rest 파라미터를 사용
4) Rest 파라미터
1. 기본 문법
- Rest 파라미터는 매개변수 이름 앞에 세개의 점 ...을 붙여서 정의한 매개변수를 말함
- Rest 파라미터는 함수에 전달된 인수들의 목록을 배열로 전달받음
- 일반 매개변수와 함께 사용 가능
- 함수에 전달된 인수들은 매개변수와 Rest 파라미터에 순차적으로 할당되며, Rest 파라미터에는 나머지 인수들이 할당되는 것이므로 반드시 마지막 파라미터여야 함
- Rest 파라미터는 단 하나만 선언 가능
- 함수 객체의 length 프로퍼티에 영향을 주지 않음
2. Rest 파라미터와 arguments 객체
- ES6에서는 rest 파라미터를 사용해서 가변 인자 함수의 인수 목록을 배열로 직접 전달받을 수 있으므로, 유사 배열 객체인 arguments 객체를 배열로 변환해야 하는 번거로움을 피할 수 있음
- 함수와 ES6 메서드는 Rest 파라미터와 arguments 객체를 모두 사용 가능
- 화살표 함수로 가변 인자 함수를 구현해야 할 때는 반드시 Rest 파라미터를 사용해야 함
5) 매개변수 기본값
- 인수 체크 및 초기화 시, 인수가 전달되지 않았을 때를 대비하여 기본값 할당이 필요(방어 코드)
- ES6에서 도입된 매개변수 기본값을 사용 시 이를 간소화할 수 있음
- 매개변수에 인수를 전달하지 않은 경우, undefined를 전달한 경우에만 유효
- Rest 파라미터에는 기본값 지정 불가
- 매개변수 기본값은 length 프로퍼티와 arguments 객채에 아무런 영향을 주지 않음
참고 : 도서 <Deep Dive 모던 자바스크립트>
'TIL' 카테고리의 다른 글
<모던 자바스크립트 Deep Dive> 24~25.5장 클로저, 클래스 요약 (0) | 2022.03.31 |
---|---|
<모던 자바스크립트 Deep Dive> 23장 실행 컨텍스트 요약 (0) | 2022.03.29 |
<모던 자바스크립트 Deep Dive> 20장~22장 strict mode, 빌트인 객체, this 요약 (0) | 2022.03.28 |
<모던 자바스크립트 Deep Dive> 19장 프로토타입 요약 (0) | 2022.03.15 |
<모던 자바스크립트 Deep Dive> 17~18장 생성자 함수에 의한 객체 생성, 함수와 일급 객체 요약 (0) | 2022.03.08 |