클래스는 프로토타입의 문법적 설탕인가?
생성자 함수와 클래스의 차이
- 클래스를 new 연산자 없이 호출하면 에러 발생 /생성자 함수를 new 연산자 없이 호출하면 일반 함수로서 호출
- 클래스는 상속을 지원하는 extends 와 super 키워드를 제공 /생성자 함수는 extends 와 super 키워드를 지원하지 X
- 클래스는 호이스팅이 발생하지 않는 것처럼 동작 /함수 선언문으로 정의된 생성자 함수는 함수 호이스팅이, 함수 표현식으로 정의한 생성자 함수는 변수 호이스팅이 발생
- 클래스 내의 모든 코드에는 암묵적으로 strict mode가 지정되어 실행되며 strict mode 해제 X /생성자 함수는 임묵적으로 strict mode 지정 X
- 클래스의 constructor, 프로토타입 메서드, 정적 메서드는 모두 프로퍼티 어트리뷰트 [[Enumerable]] 의 값이 false 열거 X
클래스는 새로운 객체 생성의 매커니즘
클래스 정의
// 클래스 선언문
class Person{} // 파스칼 케이스 사용
// 익명 클래스 표현식
const Person = class{};
// 기명 클래스 표현식
const Person = class MyClass{};
클래스는 일급 객체로 다음과 같은 특징을 가짐
- 무명의 리터럴로 생성 가능 (런타임 생성 가능)
- 변수나 자료구조 (객체, 배열 등)에 저장 가능
- 함수의 매개변수에게 전달 가능
- 함수의 반환값으로 사용 가능
- 값처럼 사용 가능
클래스 몸체에서 정의 할 수 있는 메서드는 constructor (생성자), 프로토타입 메서드, 정적 메서드 세 가지가 있음
// 클래스 선언문
class Person{
// 생성자
constructor(name){
// 인스턴스 생성 및 초기화
this.name = name; // name 프로퍼티는 public
}
// 프로토타입 메서드
sayHi(){
console.log(`프로토타입 메서드! 저는 ${this.name}입니다`);
}
// 정적 메서드
static sayHello(){
console.log("정적 메서드!")
}
}
// 인스턴스 생성
const me = new Person("Echichi");
// 인스턴스의 프로퍼티 참조
console.log(me.name); // Echichi
// 프로토타입 메서드 호출
me.sayHi(); // 프로토타입 메서드! 저는 Echichi입니다
// 정적 메서드 호출
Person.sayHello(); // 정적 메서드!
클래스 호이스팅
클래스 선언문으로 정의한 클래스는 함수 선언문과 같이 런타임 이전 (소스코드 평가 과정)에 먼저 평가되어 함수 객체 생성
→ 클래스는 constructor 생성자 함수로서 호출할 수 있는 함수로 파악되어 함수 객체를 생성하는 시점에 프로토타입도 덩달아 생성
→ 프로토타입과 생성자 함수는 단독으로 존재할 수 없고 언제나 쌍으로 존재하기 때문
const Person = '';
{
// 호이스팅이 발생하지 않는다면 ''이 출력되어야 한다
console.log(Person);
// ReferenceError : Cannot access 'Person' before initialization
// 클래스 선언문
class Person{}
}
클래스 선언문 이전에 일시적 사각지대에 빠지기 떄문에 호이스팅이 발생하지 않는 것처럼 동작
var, let, const, function, class 키워드를 사용하여 선언된 모든 식별자는 런타임 이전에 먼저 실행되기 때문에 호이스팅 됨
인스턴스 생성
클래스는 생성자 함수이며 new 연산자와 함께 호출되어 인스턴스를 생성
class 클래스명 {}
// 인스턴스 생성
const 식별자 = new 클래스명();
클래스는 인스턴스를 생성하는 것이 유일한 존재 이유이므로 반드시 new 연산자와 함께 호출해야함
const Person = class MyClass{};
const me = new Person();
const you = mew MyClass(); // ReferenceError : MyClass is not defined
기명 함수 표현식과 마찬가지로 클래스 표현식에서 사용한 클래스 이름은 외부 코드에서 접근 불가능
메서드
클래스 몸체에서 정의할 수 있는 메서드는 constructor (생성자), 프로토타입 메서드, 정적 메서드 세 가지가 있음
1. constructor
- 인스턴스를 생성하고 초기화하기 위한 특수한 메서드
- 이름 변경 불가
- 특성이 생성자 함수와 같음 (프로토타입과의 연결, 스코프 체인 구성, this)
- 모든 함수 객체가 가지고 있는 prototype 프로퍼티가 가리키는 프로토타입 객체의 constructor 프로퍼티는 클래스 자신을 가리킴 (생성자 함수 또는 리터럴 표기법으로 객체를 생성하면 프로토타입은 생성된 객체의 [[Prototype]] 내부 슬롯에 할당)
- 클래스 몸체에 정의한 constructor는 메서드로 해석되는 것이 아니라 클래스가 평가되어 constructor의 기술된 동작을 하는 함수 객체가 생성
- 클래스의 constructor 메서드와 프로토타입의 constructor은 다름 (프로토타입 constructor : 모든 프로토타입이 가지고 있는 프로퍼티이며 생성자 함수를 가리킴)
- constructor는 클래스 내에 최대 한 개만 존재 가능
- constructor는 생략 가능 = 빈 constructor 가 암묵적으로 정의 (constructor(){})
2. 프로토타입 메서드
생성자 함수를 사용하여 인스턴스를 생성하는 경우 프로토타입 메서드를 생성하기 위해서는 명시적으로 프로토타입에 메서드 추가해야함
class Person{
// 생성자
constructor(name){
// 인스턴스 생성 및 초기화
this.name = name;
}
// 프로토타입 메서드
sayHi(){
console.log(`프로토타입 메서드! 저는 ${this.name}입니다`);
}
}
const me = new Person("Echichi");
me.sayHi(); // 프로토타입 메서드! 저는 Echichi입니다
클래스 몸체에서 정의한 메서드는 prototype 프로퍼티에 추가하지 않아도 기본적으로 프로토타입 메서드가 됨
// me 객체의 프로토타입은 Person.prototype
Object.getPrototype(me) === Person.prototype; // true
me instanceof Person; // true
// Person.prototype의 프로토타입은 Object.prototype
Object.getPrototypeOf(Person.prototype) === Object.prototype; // true
me instanceof Object // true
// me 객체의 constructor는 Person 클래스
me.contructor === Person; // true
클래스가 생성한 인스턴스는 프로토타입 체인의 일원이 됨
3. 정적 메서드
정적 메서드 : 인스턴스를 생성하지 않아도 호출될 수 있는 메서드
class Person {
// 생성자
constructor(name){
// 인스턴스 생성 및 초기화
this.name = name;
}
// 정적 메서드
static sayHi(){
console.log("Hi!");
}
}
- 정적 메서드는 클래스에 바인딩된 메서드가 됨
- 클래스는 함수 객체로 평가되므로 자신의 프로퍼티/ 메서드 소유 가능
- 클래스는 클래스 정의 (클래스 선언문이나 클래스 표현식)가 평가되는 시점에서 함수 객체가 되므로 인스턴스와 달리 별다른 생성 과정 필요 X
- 클래스의 정적 메서드는 정의 이후 인스턴스를 생성하지 않아도 호출 가능
4. 정적 메서드와 프로토타입 메서드의 차이
- 정적 메서드와 프로토타입 메서드는 자신이 속해 있는 프로토타입 체인이 다르다
- 정적 메서드는 클래스로 호출하고 프로토타입 메서드는 인스턴스로 호출한다
- 정적 메서드는 인스턴스 프로퍼티를 참조할 수 없지만 프로토타입 메서드는 인스턴스 프로퍼티를 참조할 수 있다
- 정적 메서드는 클래스를 호출해야 하므로 정적 메서드 내부의 this 는 인스턴스가 아닌 클래스를 가리킨다
- 표준 빌트인 객체인 Math, Number, JSON, Object, Reflect 등은 다양한 정적 메서드를 가지고 있으며 이 메서드들은 애플리케이션 전역에서 사용할 유틸리티 함수다
// 표준 빌트인 객체의 정적 메서드
Math.max(1, 3); // 3
Number.isNaN(NaN); // true
JSON.stringify({ a : 1 }) // "{ 'a' : 1 }"
5. 클래스에서 정의한 메서드의 특징
- function 키워드를 생략한 메서드 축약 표현을 사용
- 객체 리터럴과는 다르게 클래스에 메서드를 정의할 때는 콤마가 필요 X
- 암묵적으로 strict mode로 실행
- 프로퍼티 어트리뷰트 [[Enumerable]] 값이 false
- 내부 메서드 [[Construct]] 를 갖지 않는 non-contruct → new 연산자와 함께 호출 불가
클래스 의 인스턴스 생성 과정
1. 인스턴스 생성과 this 바인딩
- new 연산자와 함께 클래스를 호출하면 constructor의 내부 코드가 실행되기에 앞서 암묵적으로 빈 객체 생성 ( 이 빈 객체가 완성되진 않은 인스턴스)
- 클래스가 생성한 인스턴스의 프로토타입으로 클래스의 prototype 프로퍼티가 가리키는 객체가 설정 됨
- 생성된 빈 객체 즉 인스턴스는 this 에 바인딩
- constructor 내부의 this 는 클래스가 생성한 인스턴스를 가리킴
2. 인스턴스 초기화
- constructor의 내부 코드가 실행되어 this에 바인딩되어 있는 인스턴스에 프로퍼티 추가
- constructor 가 인수로 전달받은 초기값으로 인스턴스의 프로퍼티 값 초기화
3. 인스턴스 반환
- 클래스의 모든 처리가 끝나면 완성된 인스턴스가 바인딩된 this 가 암묵적으로 반환
class Person {
// 생성자
constructor(name){
// 1. 암묵적으로 인스턴스가 생성(빈 객체)되고 this에 바인딩 됨
console.log(this); // Person{}
// 클래스가 생성한 인스턴스의 프로토타입 === 클래스의 prototype 프로퍼티 객체
console.log(Object.getPrototypeOf(this) === Person.prototype); // true
// 2. this에 바인딩되어 있는 인스턴스 초기화
this.name = name;
// 3. 완성된 인스턴스가 바인딩된 this 가 암묵적으로 반환
}
}
프로퍼티
1. 인스턴스 프로퍼티
인스턴스 프로퍼티는 constructor 내부에서 정의해야 함
constructor 내부에서 this 에 인스턴스 프로퍼티 추가 (= 생성자 함수가 생성할 인스턴스의 프로퍼티를 정의하는 것과 비슷) → 인스턴스에 프로퍼티가 추가되어 인스턴스가 초기화 됨
2. 접근자 프로퍼티
접근자 프로퍼티는 자체적으로 값 ([[Value]]내부 슬롯)을 갖지 않고 다른 데이터 프로퍼티의 값을 읽거나 저장할 때 사용하는 접근자 함수로 구성된 프로퍼티
class Person {
constructor (firstName, lastName){
this.firstName = firstName;
this.lastName = lastName;
}
// fullName은 접근자 함수로 구성된 접근자 프로퍼티
// getter 함수
get fullName(){
return `${this.lastName} ${this.firstName}`;
}
// setter 함수
set fullName(name){
[this.lastName, this.firstName] = name.split(' ');
}
}
const me = new Person('chichi', 'E');
// 데이터 프로퍼티를 통한 프로퍼티 값의 참조
console.log(`${me.lastName} ${me.firstName}`); // E chichi
// 접근자 프로퍼티를 통한 프로퍼티 값의 저장
// 접근자 프로퍼티 fullName에 값을 저장하면 setter 함수가 호출됨
me.fullName = "A chiyak";
console.log(me); // {firstName : "chiyak", lastName : "A" }
// 접근자 프로퍼티를 통한 프로퍼티 값의 참조
// 접근자 프로퍼티 fullName에 접근하면 getter 함수가 호출됨
console.log(me.fullName); // A chichi;
// fullName 은 접근자 프로퍼티다
// 접근자 프로퍼티는 get, set, enumerable, configurable 프로퍼티 어트리뷰트를 가짐
console.log(Object.getOwnPropertyDescriptor(Person.property, 'fullName'));
// {get : f, set: f, enumerable : false, configurable : true}
| getter | setter |
| 호출하는 것이 아니라 프로퍼티처럼 참조하는 형식으로 사용 | 호출하는 것이 아니라 프로퍼티처럼 값을 할당하는 형식으로 사용 |
| 반드시 무언가를 반환 | 반드시 매개변수 필요 (단 하나의 값) |
클래스의 메서드 = 프로토타입 메서드 → 클래스의 접근자 프로퍼티 = 프로토타입 프로퍼티
3. 클래스 필드 정의 제안
클래스 필드 : 클래스 기반 객체 지향 언어에서 클래스가 생성할 인스턴스의 프로퍼티를 가리키는 용어
최신 브라우저 또는 최신 Node.js(버전 12 이상) 에서는 클래스 필드를 클래스 몸체에 정의 가능
class Person{
// 클래스 필드 정의
name = "Echichi";
}
const me = new Person();
console.log(me); // Person {name : "Echichi"}
- 클래스 필드를 참조하는 경우 this 를 반드시 사용해야함
- 클래스 필드에 초기값을 할당하지 않으면 undefined
- 인스턴스를 생성할 때 외부의 초기값으로 클래스 필드를 초기화해야 한다면 constructor 에서 클래스 필드를 초기화 해야함
- 클래스 필드를 통해 메서드 정의 가능 → 프로토타입 메서드가 아닌 인스턴스 메서드가 됨 ( 클래스 필드는 인스턴스 프로퍼티이기 때문 )
4. private 필드 정의 제안
최신 브라우저 또는 최신 Node.js(버전 12 이상) 에서는 private 필드 정의 가능
private 필드의 선두에 #을 붙이고 private 필드를 참조할 때도 #을 붙임
class Person{
// private 필드 정의
#name = '';
constructor(name){
// private 필드 참조
this.#name = name;
}
// 접근자 프로퍼티 name
get sayName(){
// private 필드를 참조하여 trim한 다음 반환
return this.#name.trim();
}
}
const me = new Person("Echichi");
// private 필드 #name 은 클래스 외부에서 참조불가
console.log(me.#name);
// SyntaxError : Private field must be declared in an enclosing class
console.log(me.sayName); // Echichi
접근자 프로퍼티를 통해 간접적으로 접근하는 방법은 유효
private 필드는 반드시 클래스 몸체에 정의해야하며 constructor에 정의하면 에러
| 접근 가능성 | public | private |
| 클래스 내부 | O | O |
| 자식 클래스 내부 | O | X |
| 클래스 인스턴스를 통한 접근 | O | X |
5. static 필드 정의 제안
최신 브라우저 또는 최신 Node.js(버전 12 이상) 에서는 static public/ private 필드 정의 가능
class MyMath{
// static public 필드 정의
static PI = 22 / 7;
// static private 필드 정의
static #num = 10;
// static 메서드
static increment(){
return ++My.Math.#num;
}
}
console.log(MyMath.PI); // 3.141592
console.log(MyMath.increment()); // 11
상속에 의한 클래스 확장
1. 클래스 상속과 생성자 함수 상속
상속에 의한 클래스 확장은 기존 클래스를 상속받아 새로운 클래스를 확장 정의 하는 것

class Animal{
constructor(age, weight){
this.age = age;
this.weight = weight;
}
eat(){ return 'eat'; }
move(){ return 'move'; }
}
// 상속을 통해 Animal 클래스를 확장한 Bird 클래스
class Bird extends Animal{
fly(){ return 'fly' }
}
const bird = new Bird(1, 5);
console.log(bird); // Bird{ age : 1 , weigth : 5}
console.log(bird instanceof Bird); // true
console.log(bird instanceof Animal); // true
console.log(bird.eat()); // eat
console.log(bird.move()); // move
console.log(bird.fly()); // fly
2. extends 키워드

상속을 통해 클래스를 확장하려면 extends 키워드를 사용하여 상속받을 클래스를 정의
// 수퍼(베이스/부모) 클래스
class Base{}
// 서브(파생/자식) 클래스
class Derived extends Base{}
서브클래스 : 상속을 통해 확장된 클래스 (파생 클래스, 자식 클래스)
수퍼클래스 : 서브클래스에게 상속된 클래스 (베이스 클래스, 부모 클래스)
3.동적 상속
- extends 키워드는 클래스뿐만 아니라 [[Construct]] 내부 메서드를 갖는 함수 객체로 평가될 수 있는 모든 표현식 (생성자 함수)을 상속받아 클래스 확장 가능
- extends 앞에는 반드시 클래스가 와야함
- 동적으로 상속받을 대상 결정 가능
function Base1(){}
class Base2 {}
let condition = true;
// 조건에 따라 동적으로 상속 대상을 결정하는 서브 클래스
class Derived extends (condition ? Base1 : Base2){}
const derived = new Derived();
console.log(derived); // Derived{}
console.log(derived instanceof Base1); // true
console.log(derived instanceof Base2); // false
4. 서브클래스의 constructor
슈퍼클래스와 서브클래스 모두 constructor를 생략하면 빈 객체가 생성됨 → 프로퍼티를 소유하는 인스턴스를 생성하려면 constructor 내부에서 인스턴스에 프로퍼티를 추가해야함
// 수퍼클래스
class Base {
constructor(){}
}
// 서브 클래스
class Derived extends Base{}
/*
위의 수퍼클래스에는 다음과 같이 암묵적으로 constructor가 정의됨
class Base {
constructor(){}
}
*/
/*
위의 서브클래스에는 다음과 같이 암묵적으로 constructor가 정의됨
class Derived extends Base{
constructor(...args){ super(...args); }
}
*/
5. super 키워드
super 키워드 : 함수처럼 호출할 수도 있고 this와 같이 식별자처럼 참조할 수 있는 특수한 키워드
- super를 호출하면 수퍼클래스의 constructor(super-constructor)를 호출한다
- super를 참조하면 수퍼클래스의 메서드를 호출할 수 있다
- super 호출
super를 호출하면 수퍼클래스의 constructor(super-constructor)를 호출한다
- 수퍼클래스의 constructor 내부에서 추가한 프로퍼티를 그대로 갖는 인스턴스를 생성한다면 서브클래스의 constructor 생성 가능
- new 연산자와 함께 서브클래스를 호출하면서 전달한 인수는 모두 서브클래스에서 암묵적으로 정의된 cosntructor의 super 호출을 통해 수퍼클래스의 constructor 에 전달됨
// 수퍼 클래스
class Base{
// ④ Base 클래스의 constructor에 일부가 전달
constructor(a,b){
this.a = a;
this.b = b;
}
}
// 서브 클래스
class Derived extends Base {
// constructor 작성 생략시 다음과 같이 암묵적으로 constructor가 정의됨
// constructor(...args) { super(...args);}
constrcutor(a, b, c){ // ② Derived 클래스에 인수 전달
// ③ super 호출
super(a, b);
this.c = c;
}
}
// 수퍼클래스의 constructor 에 전달할 필요가 있는 인수는 서브클래스의 constructor에서 호출하는 super을 통해 전달
// // ① Derived 클래스 호출
const derived = new Derived(1, 2);
console.log(derived); // Derived {a: 1, b: 2}
super 호출 시 주의사항
- 서브클래스에서 constructor를 생략하지 않는 경우 서브 클래스의 constructor에서는 반드시 super 을 호출해야한다
- 서브클래스의 constructor 에서 super를 호출하기 전에는 this 를 참조할 수 없다
- super는 반드시 서브클래스의 constructor에서만 호출한다. 서브클래스가 아닌 클래스의 constructor나 함수에서 super를 호출하면 에러가 발생한다
- super 참조
super를 참조하면 수퍼클래스의 메서드를 호출할 수 있다
서브클래스의 프로토타입 메서드 내에서 super.메서드는 수퍼클래스의 프로토타입 메서드를 가리킨다
- super 참조를 통해 수퍼클래스의 메서드를 참조하려면 super가 수퍼클래스의 메서드가 바인딩된 객체 , 즉 수퍼클래스의 prototype 프로퍼티에 바인딩된 프로토타입을 참조할수 있어야 한다
// 수퍼클래스
class Base{
constructor(name){
this.name = name;
}
sayHi(){
return `수퍼클래스! ${this.name}`;
}
}
class Derived extends Base{
sayHi(){
// __super 는 Base.prototype 을 가리킨다
const __super = Object.getPrototypeOf(Derived.prototype);
return `${__super.sayHi.call(this)} 난 서브클래스!`;
}
}

super 참조가 동작하기 위해서는 super를 참조하고 있는 메서드(Derived.sayHi)가 바인딩되어 있는 객체(Derived.prototype)의 프로토타입(Base.prototype)을 찾을 수 있어야 함
이를 위해 메서드는 내부 슬롯 [[HomeObject]] 를 가지며 자신을 바인딩하고 있는 객체를 가리킴
super 참조의사를 코드로 표현
/*
[[HomeObject]]는 메서드 자신을 바인딩하고 있는 객체를 가리킨다
[[HomeObject]]를 통해 매서드 자신을 바인딩하고 있는 객체의 프로토타입을 찾을 수 있다
예를 들어 Derived 클래스의 sayHi 메서드는 Derived.prototype에 바인딩 되어 있다
따라서 Derived 클래스의 sayHi 메서드의 [[HomeObject]]는 Derived.prototype이고
이를 통해 Derived 클래스의 sayHi 메서드 내부의 super 참조가 Base.prototype 으로 결정된다
따라서 super.sayHi는 Base.prototype.sayHi를 가리키게 된다
*/
super = Object.getPrototypeOf([[HomeObject]])
const obj = {
// foo는 ES6의 메서드 축약 표현으로 정의한 메서드다. 따라서 [[HomeObject]]를 갖는다
foo(){}.
// bar는 ES6의 메서드 축약 표현으로 정의한 메서드가 아니라 일반 함수로 [[HomeObject]]를 갖지 않는다
bar : function(){}
};
- [[HomeObject]] 를 가지는 함수만이 super 를 참조 가능 → ES6의 메서드 축약표현으로 정의된 함수만이 super 참조 가능
서브클래스의 정적 메서드 내에서 super.sayHi는 수퍼클래스의 정적 메서드 sayHi를 가리킨다
// 수퍼클래스
class Base{
static sayHi(){
return "Hi";
}
}
// 서브클래스
class Derived extends Base{
static sayHi(){
// super.sayHi 는 수퍼클래스의 정적 메서드를 가리킨다
return `${super.sayHi()}! Echichi`;
}
}
6. 상속 클래스의 인스턴스 생성 과정
1. 서브클래스의 super 호출
- 자바스크립트 엔진은 클래스를 평가할 때 다른 클래스를 상속받지 않는 클래스 (그리고 생성자 함수)는 내부슬롯 [[ConstructorKind]] 값으로 base를 설정하고 다른 클래스를 상속받는 서브클래스는 derived로 설정
- 다른 클래스를 상속받지 않는 클래스(그리고 생성자 함수) 는 new 연산자와 함께 호출되었을 때 암묵적으로 빈 객체 즉 인스턴스를 생성하고 이를 this 에 바인딩
- 서브클래스는 자신이 직접 인스턴스를 생성하지 않고 수퍼클래스에게 인스턴스 생성을 위임 → 서브클래스의 constructor에서 반드시 super 을 호출해야하는 이유
2. 수퍼클래스의 인스턴스 생성과 this 바인딩
- new 연산자와 함께 호출된 클래스는 서브클래스로 생성된 인스턴스는 new.target이 가리키는 서브클래스가 생성한 것으로 처리
3. 수퍼클래스의 인스턴스 초기화
- this에 바인딩 되어 있는 인스턴스에 프로퍼티를 추가하고 constructor가 인수로 전달받은 초기값으로 인스턴스의 프로퍼티 초기화
4. 서브클래스 constructor로의 복귀와 this 바인딩
- super 호출이 종료되고 제어 흐름이 서브클래스 constructor로 복귀
- super가 반환한 인스턴스가 this에 바인딩
- 서브클래스는 별도의 인스턴스를 생성하지 않고 super 가 반환한 인스턴스를 this에 바인딩하여 그대로 사용 → super 가 호출되지 않으면 인스턴스가 생성되지 않고 this 바인딩도 못하기 때문에 this 참조 불가
5. 서브클래스의 인스턴스 초기화
- this에 바인딩되어 있는 인스턴스에 프로퍼티를 추가하고 constructor가 인수로 전달받은 초기값으로 인스턴스의 프로퍼티 초기화
6. 인스턴스 반환
- 클래스의 모든 처리가 끝나면 완성된 인스턴스가 바인딩된 this 가 암묵적으로 반환
7. 표준 빌트인 생성자 함수 확장
// Array 생성자 함수를 상속받아 확장한 MyArray
class MyArray extends Array{
// 중복된 배열 요소를 제거하고 반환한다
// MyArray클래스의 인스턴스 반환
uniq(){
return this.filter((v, i, self)=>(self.indexOf(v) === i));
}
// 모든 배열 요소의 평균을 구한다
// MyArray클래스의 인스턴스 반환
avg(){
return this.reduce((pre, cur)=>(pre + cur, 0))/ this.length;
}
}
const myArray = new Array(1, 1, 2, 3);
console.log(myArray.uniq()); // MyArray(3) [1, 2, 3]
console.log(myArray.avg()); // 1.75
// MyArray 클래스 인스턴스를 반환하기 때문에 메서드 체이닝 가능
console.log(myArray.filter((v)=>(v % 2)).uniq().avg())'Javascript' 카테고리의 다른 글
| [모던 자바스크립트 Deep Dive] 24. 배열 (2) | 2023.11.22 |
|---|---|
| [모던 자바스크립트 Deep Dive] 23. ES6함수의 추가 기능 (0) | 2023.11.20 |
| [모던 자바스크립트 Deep Dive] 21. 클로저 (0) | 2023.11.16 |
| [모던 자바스크립트 Deep Dive] 20. 실행 컨텍스트 (1) | 2023.11.15 |
| [모던 자바스크립트 Deep Dive] 19. this (0) | 2023.11.14 |