JavaScript

Class body와 메서드 정의

단점이없어지고싶은개발자 2022. 7. 20. 11:54
반응형

Class는 객체를 생성하기 위한 템플릿이다. 클래스는 데이터와 이를 조작하는 코드를 하나로 추상화한다. 자바스크립트에서 클래스는 프로토타입을 이용해서 만들어졌지만 ES5의 클래스 의미와는 다른 문법과 의미를 가진다.

Class 정의

Class는 특별한 함수다 함수도 표현식, 선언식이 있는 것처럼 class문법 또한 표현식, 선언식으로 나눠져있다.

Class 선언

선언하기 위해서는 클래스의 이름과 함께 class 키워드를 사용해야 한다

class Rectangle {
	constructor(height, widht) {
		this.height = height;
		this.width = width;
	}
}

Hosting

함수 선언과 클래스 선언의 중요한 차이점은 함수의 경우 정의하기 전에 호출할 수 있지만(호이스팅 되어서 최상단으로 끌어올려진다), 클래스는 반드시 정의한 뒤에 사용할 수 있다는 점이다. 만약 호출하면 ReferenceError 발생

Class 표현

class 표현식의 이름은 클래스 body의 local scope에 한해 유효하다.

//이름이 없는 경우
let Rectangle = class {
	constructor(height, width) {
		this.height = height;
		this.width = width;
	}
};

console.log(Rectangle.name); // Rectangle

let Rectangle = class Rectangle2 {
		constructor(height, width) {
		this.height = height;
		this.width = width;
	}
};

console.log(Rectangle.name); // Rectangl2

Class Body와 메서드 정의

class body는 중괄호 {} 로 묶여 있는 안쪽 부분이다. 이곳은 여러분이 메서드나 constructor와 같은 class 멤버를 정의

Strict mode

클래스의 본문(body)은 strict mode에서 실행된다. 즉, 여기에 적힌 코드는 성능 향상을 위해 더 엄격한 문법이 적용된다.

Constructor(생성자)

constructor 메서드는 class로 생성된 객체를 초기화하기 위한 특수한 메서드이다. ‘constructor’라는 이름을 가진 특수한 메서드는 클래스 안에 한 개만 존재할 수 있다. 여러 개를 사용하면 SyntaxError가 발생한다.

constructor는 부모 클새의 constructor를 호출하기 위해 super 키워드를 사용할 수 있다

프로토타입 메서드

class Rectangle { 
	constructor(height, width) {
		this.height = height;
		this.width = width;
	}
	//Getter
	get area() {
		return this.calcArea();
	}
	//메서드
	calcArea() {
		return this.height * this.width;
	}
}

const square = new Rectangle(10, 10);

console.log(square.area); // 100

정적 메서드와 속성

static 키워드는 클래스를 위한 정적(static)메서드를 정의한다. 정적 메서드는 클래스의 인스턴스화 없이 호출되며, 클래스의 인스턴스에서는 호출할 수 없다. 정적 메서드는 어플리케이션을 위한 유틸리티 함수를 생성하는데 주로 사용된다. 반면, 정적 속성은 캐시, 고정 환경설정 또는 인스턴스 간에 복제할 필요가 없는 기타 데이터에 유용하다.

즉, static을 쓰면 Class의 인스턴스화 없이 호출되며 인스턴스화 시키더라도 호출 할 수 없다.

class foo {
    constructor(name) {
        this.name = name;
    }
    static sayHello() {
        console.log('hello');
    }
}

foo.sayHello(); //hello가 나온다

let temp = new foo();

temp.sayHello(); //VM2704:1 Uncaught TypeError: temp.sayHello is not a function

프로토타입 및 정적 메서드를 사용한 this 바인딩

메서드를 변수에 할당 한 다음 호출하는 것과 같이, 정적 메서드나 프로토타입 메서드가 this값 없이 호출될 때, this값은 메서드 안에서 undefined가 된다. 이 동작은 ‘use strict’ 명령어 없이도 같은 방식으로 동작하는데, class문법 안에 있는 코드는 항상 strict mode로 실행되기 때문이다.

class Animal {
	speak() {
		return this;
	}
	static eat() {
		return this;
	}
}

let obj = new Animal();
obj.speak(); // the Aniaml object
let speak = obj.speak;
speak; // undefined

Animal.eat(); // class Animal
let eat = Animal.eat;
eat(); // undefined

위의 작성된 코드를 전통적 방식의 함수기반인 non-strict mode 구문으로 재작성하면, this 메서드 호출은 기본적으로 전역 객체인 초기 this값에 자동으로 바인딩 된다. Strict mode에서는 자동 바인딩이 발생하지 않는다. this값은 전달된 대로 유지된다.

function Animal() {}

Animal.prototype.speak = function() {
	return this;
}

Animal.eat = function() {
	return this;
}

let obj = new Animal();
let speak = obj.speak;

speak(); // global object

let eat = Animal.eat;
eat(); // global object

인스턴스 속성

인스턴스 속성은 반드시 클래스 메서드 내에 정의되어야 한다.

class Rectangle {
	constructor(height, width) {
		this.height = height;
		this.width = width;
	}
}

정적 (클래스사이드)속성과 프로토타입 데이터 속성은 반드시 클래스 바깥쪽에서 정의되어야 한다.

Rectangle.staticWidth = 20;
Rectangle.prototype.prototypeWidth = 25;

Public 필드 선언

자바스크립트의 필드 선언 문법을 사용해서 위의 예제는 아래와 같이 쓰여진다.

필드를 먼저 선언함으로서 클래스 정의는 self-documenting에 가까워졌고 필드는 언제나 존재하는 상태가 된다.

class Rectangle {
	heigth = 0;
	width;
	constructor(height, width) {
		this.height = height;
		this.width = width;
	}
}

Private 필드 선언

Private필드를 사용하면 아래와 같이 예제를 개선할 수 있다.

class Rectangle {
	#heigth = 0;
	#width;
	constructor(height, width) {
		this.#height = height;
		this.#width = width;
	}
}

클래스의 바깥에서 private필드를 접근하려고 하면 에러가 발생한다. private필드는 클래스 내부에서만 읽고 쓰기가 가능하다.

반응형