본문 바로가기

TIL

<모던 자바스크립트 Deep Dive> 25.6~26장 클래스, ES6 함수의 추가 기능 요약

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 모던 자바스크립트>