Class 란?

Minju Kim·2022년 2월 9일
0

JavaScript

목록 보기
3/7
post-thumbnail

엘리님 class강의를 듣고 정리한 내용입니다.

class에 관한 몇 가지

  • class : template
  • object : instance of a class
  • JavaScript classes
    • introduced in ES6 (그 전까지는 function을 이용해서 template을 만들었었다)
    • syntactical sugar over prototype-based inheritance

1. Class declaration : 클래스 선언 방법

// 클래스 선언
class Person {
	constructor(name, age) {
		this.name = name;
		this.age = age;
	  speak(){
				console.log(`${this.name}: hello!`);
}

// 민주 만들기
const minju = new Person('minju', 20);
minju.speak();

2. Getter and Setters

class User {
	constructor(firstName, lastName, age) {
		this.firstName = firstName;
		this.lastName = lastName;
		this.age = age;
	}

	// 값을 리턴하고
	get age(){
		return this._age;
	}

	// 값을 설정할 수 있다. 어떤 값을 설정할 것인가? 알아야 하기 때문에 value를 받아와야 한다.
	set age(value){
		this._age = value < 0 ? 0 : value; // 0보다 작은 숫자를 넣었으면 0를 보내줘라~
	}
}

// 그런데, 말도 안되는 값을 넣으면 어떡하지? 나이가 -1 살이 될 수 있나?
// 사용자가 잘못 사용해도 방어해 줄 수 있는 것이 게터와 세터!
const user1 = new User('Steve', 'Jobs', -1);  

💡getter와 setter가 어떻게 동작하는 방법!

우리가 getter를 정의하게 되면, this.age가 메모리에 저장된 값을 읽어오는게 아니라, get age()라는 함수를 실행하게 된다.

그리고 우리가 setter를 정의하는 순간, 값을 할당할 때 =age로 받아온 값을 바로 할당하는 것이 아니라, setter를 실행하게 된다. 그런데, this.age = value라고 되어 있으니, 또 다시 그 함수를 호출하게 되고, 또 호출하게 되고, 그렇게 콜 스택 사이즈 초과 에러가 나오게 된다.

➡️ 이를 방지하기 위해, getter와 setter안의 변수를 조금 다른 걸로 만들어줘야 한다. 보통 변수 앞에 _ underscore을 달아 표현한다. _age

3. Fields (public, private) - too soon!

class를 만들때 constructor를 사용하지 않고 만드는 방식인데, too soon! 아직 여러 브라우저들에서 지원이 되지 않는다.

// constructor 없이 class를 만든다. 
// publicfield는 class 밖에서도  
class Experiment {
	publicField = 2;
	#privateField = 0;
}

const experiment = new Experiment();

console.log(experiment.publicField);   // 2
console.log(experiment.privateField);  // undefined

4. Static properties and methods - too soon!

간혹 생기는 오브젝트에 상관없이 동일하게 반복적으로 가지고 있는 프로퍼티와 메소드가 있을 수 있다. 그럴 때, 앞에 static을 붙여줘서, 그 프로퍼티/메소드는 클래스에 붙어있게 만들 수 있다.

class Article {
	static publisher = 'Dream coding';
	constructor(articleNumber) {
		this.articleNumber = articleNumber;
	}

	static publisher() {
		console.log(Article.publisher);  // 이 부분에서 this대신 class명 사용한 걸 주목!
	}
}

const article1 = new Article(1);
console.log(article1.publisher); // undefined값이 나온다. 
console.log(Article.publisher); // 'Dream coding'이 정상적으로 출력된다.

상속과 다양성

1. 상속 : a way for one class to extend to another class

내가 직사각형, 삼각형, 원을 만들수 있는 클래스를 만든다고 할 때, 어떻게 만드는게 가장 효율적일까?

넓이 높이 등을 공통적으로 가지고 있기 때문에, Shape을 공통적으로 만들어서 이 도형들을 만들어주면 된다!

2. 다양성 : 원하는 부분만 오버라이딩 해 줄 수 있다.

다른 클래스의 속성을 extends로 받아왔다! 그런데 메소드 하나만 조금 변경하고 싶다면?

그 부분을 overriding 해주면 된다!

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

	draw(){
		console.log(`drawing ${this.color} color of`);
	}

	getArea(){
		return this.width * this.height;
	}
}

class Rectagle extends Shape{} // Shape의 속성들을 그대로 상속해온다.

const rectangle = new Rectangle(20, 20, 'blue');
rectangle.draw();  
// drawing blue color of 가 출력된다.

/* 다양성 */
// 삼각형의 경우에는 넓이 구하는 공식이 다르다. 이 때는 어떻게? 그 부분만 재정의 overriding 해주기!
class Triangle extends Shape{
	getArea(){
		return (this.width * this.height) / 2;
	}
	
// 공통적으로 가지고 있는 그리는 메소드도 사용하고 싶고, 추가로 새로운 기능도 해주고 싶다! 
	draw(){
		super.draw(); // 'super'라는 키워드를 사용해주면 된다!
		console.log() // 그리고 수정원하는 곳은 overriding해주면 된다.
		}
}

const triangle = new Triangle(20, 20, 'red');c
console.log(triangle);// 기존 draw와 새로 작성한 삼각형이 모두 출력된다.ㄱ

다음으로는 https://ko.javascript.info/class 를 보며 추가로 작성해보며 클래스에 대해 완전 정복 해보자!

클래스와 기본 문법

클래스와 기본 문법

  1. 기본문법

    class MyClass{
    // 여러 메서드를 정의할 수 있음
    	constructor(){...}
    	method1() {...}
    	method2() {...}
    }
    
    // 예시 : 클래스 만들기
    class User{
    
    	constructor(name){
    		this.name = name;
    	}
    
    	sayHi() {
    		console.log(`Hi, ${this.name});
      }
    }
    
    // 예시 : 클래스로 오브젝트 만들기
    const minju = new User(minju);
    minju.sayHi();  
    // Hi, minju!

클래스를 만들 때는 메서드 사이에 쉼표를 넣지 않아야 한다!!

2 . 클래스란

클래스는 새로운 개체가 아니라 함수의 한 종류이다!

```jsx
class User{
	constructor(name){this.name =  name;}
	sayHi() {alert(this.name)}
}

// User가 함수라는 증거
alert(typeof User); //function

```

 1) `User`라는 이름을 가진 함수를 만드는데, 본문은 생성자 메서드 `constructor`에서 가져온다. 생성자   메서드가 없으면 본문이 비어있는 함수가 만들어진다.

2) `sayHi`같은 클래스 내에서 정의한 메서드를 `User.prototype`에 저장한다.

3) `new User`를 호출해 객체를 만들고, 객체의 메서드를 호출하면 메서드를  prototype 프로퍼티를 통해 가져온다. 그렇기에 객체에서 클래스의 메서드를 접근할 수 있는 것이다.
  1. 클래스는 단순한 편의 문법(syntactic sugar : 기능은 동일하나 기존 문법을 쉽게 읽을 수 있게 만든 문법)이 아니다.

    물론 순수 함수 작성식으로 클래스의 역할을 하는 함수를 작성할 수가 있다. 그러나! class로 만든 함수엔 특수 내부 프로퍼티인 [[IsClassConstructor]]:true가 이름처럼 따라붙고 이를 다양한 경우에 활용한다.` 이에 대해서는 추후 경험하게 될 것.

  2. 클래스 표현식

    함수처럼 클래스도 다른 표현식 내부에서 정의, 전달, 반환, 할당할 수 있다.

    4-1. 클래스 표현식 만들기 → 클래스에 이름 안 넣어줌

    let User = class {
    	sayHi() {
    		alert("안녕하세요.")
    	}
    };
    
    new User().sayHi(); // 새로운 유저를 만들고, (함수실행시켜줘야 하기 때문에 괄호 넣어줌)
    // sayHi()메서드를 실행해라.

    4-2. 기명 함수 표현식 (Named Function Expression) → 클래스에 이름 넣어줌

    let User = class MyClass {
    	sayHi() {
    		alert(MyClass); // MyClass는 오직 클래스 안에서만 사용 가능
    	}
    };
    
    new User().sayHi();

    4-3. 필요에 따라 동적으로 클래스 생성

    // 클래스를 선언하고 반환하는 함수를 선언
    function makeClass(phrase){
    	return class{
    		sayHi(){
    			alert(phrase);
    		};
    	};
    }
    
    // 새로운 클래스 만들기
    const User = makeClass("안녕하세요");
    new User().sayHi(); // 안녕하세요.
  1. getter와 setter

    getter와 setter는 User.prototype에 정의된다.

    class User{
    	constructor(name){
    		this.name = name;
    	}
    	get name(){
    		return this._name;
    	}
    	set name(value){
    		if(value.length < 4){
    			alert("이름이 너무 짧습니다.");
    			return;
    		}
    		this._name = value;
    	}
    }
    
    const minju = new User("minju");
    console.log(minju.name);
  2. 계산된 메서드 이름 [...]

    class User {
    	['say'+'Hi'](){
    			alert("Hello");
    	}
    }
    
    const minju = new User();
    console.log(minju.sayHi());
  3. 클래스 필드

    엘리님이 알려주신 대로 프로퍼티 이름 = 값을 써주면 간단히 클래스 필드를 만들 수 있다.

profile
⚓ A smooth sea never made a skillful mariner

0개의 댓글