클래스와 인스턴스(feat. 객체 지향 프로그래밍)

moono·2023년 1월 13일
0

JavaScript

목록 보기
18/23

클로저 모듈 패턴

메서드 호출은 객체.메서드() 같이 객체 내에 메서드를 호출하는 방법을 의미
(메서드 호출 방식은 화살표 함수를 쓰지 않음!!)

클로저 모듈 패턴 을 이용하면 똑같은 기능을 하는걸 여러개 만들지 않고, 하나로 재사용하기

// 하나의 객체만 만들 수 있는데 만약 똑같은 기능을 하는 카운터가 여러 개 필요하면, 
// 그대로 복붙해야되니 재사용성이 떨어짐

let counter1 = {
  value: 0,
  increase: function() {
    this.value++ // 메서드 호출을 할 경우, this는 counter1을 가리킵니다
  },
  decrease: function() {
    this.value--
  },
  getValue: function() {
    return this.value
  }
}

counter1.increase() // console.log(counter1.value) // 1
counter1.increase() // console.log(counter1.value) // 2
counter1.increase() // console.log(counter1.value) // 3
counter1.decrease() // console.log(counter1.value) // 2
counter1.getValue() // 2

////////////////////////////////////////////////////////

// 클로저 모듈 패턴
// 똑같은 기능을 하는걸 여러개 만드는 방법 중 하나
function makeCounter() {
  let value = 0;
  return {
    increase: function() {
      value++;
    },
    decrease: function() {
      value--;
    },
    getValue: function() {
      return value;
    }
  }
}

let counter1 = makeCounter()
counter1.increase()
counter1.getValue() // 1

let counter2 = makeCounter()
counter2.decrease()
counter2.decrease()
counter2.getValue() // -2



클래스와 인스턴스

객체 지향 프로그래밍은
하나의 모델이 되는 청사진(blueprint)를 만들고, ⇒ class
그 청사진을 바탕으로 한 객체를 만든다. ⇒ instance

클래스 (ES5, ES6)

//ES5 ) 함수로 정의할 수 있다.
function Car(brand, name, color) {
  // 인스턴스가 만들어질 때 실행되는 코드
}

//ES6 ) class 라는 키워드를 사용해 정의할 수 있다.
class Car {
  constructor(brand, name, color) {
  // 인스턴스가 만들어질 때 실행되는 코드
  }
}
  • constructor : 생성자 함수로, 인스턴스가 만들어질 때 실행되는 코드이며 return 값을 만들지 않는다.
    ⇒ 클래스 내부에 딱 한 개만 존재할 수 있다.

인스턴스

  • new 키워드 통해 클래스의 새로운 인스턴스를 만들 수 있다.

  • 인스턴스 생성 즉시 생성자 함수(constructor)가 실행되며,
    변수에 클래스의 설계를 가진 새로운 객체(인스턴스) 가 할당

  • 각각의 인스턴스는 클래스의 고유한 속성과 메소드를 갖게 된다.

속성과 메서드

클래스에 속성과 메소드를 정의하고, 인스턴스에서 사용한다.

  • 속성

    • ex : 자동차의 브랜드, 차 이름, 색상 등
      ⇒ brand, name, color...
  • 메서드

    • ex : '객체에 딸린 함수' : 속력설정, 운전 등
      ⇒ setSpeed(), drive()...

메서드 소소한 팁 (feat. 진완선생님)

ES5의 메서드와 ES6의 메서드는 다른데,
ES5에서의 this.notice = function(name){...} 과
Person.prototype.notice = function(name) {...} 은 다르다

this.notice = function(name){ // 메서드
       alert(this.name);
   }
Person.prototype.notice = function(name){ // 메서드
       alert(this.name);
   }

위의 notice 메서드를 가지고 있는 클래스를 a인스턴스와 b인스턴스에 할당됐을 때?
각각 다른 주소값을 가지는 notice가 되어서
a.notice === b.notice 는 false 가 나오고

아래의 notice 메서드를 가지고 있는 클래스를 c인스턴스와 d인스턴스에 할당했을 땐
prototype.notice 라는 주소값?을 c.notice 와 d.notice 가 같이 바라보고 있어서 c.notice === d.notice 는 true 가 나온다.
(라고 나는 이해했따..ㅎ_ㅎ)

필드(Filed)

클래스에 정의할 수 있는 프로퍼티
클래스 내부에 키(프로퍼티 이름) = 값 형식으로 작성할 수 있고,
객체.키 로 접근이 가능하다

class User {
  name = "moon";
  age = "secret";
}

const newUser =  new User();

console.log(newUser.name); // moon
console.log(newUser.age); // secret

클래스 만들기

// 생성자 함수(ES5 클래스 작성 문법)사용
function Person(name){
	this.name = name; // 속성
  
  	Person.prototype.notice = function(name){ // 메서드
       alert(this.name);
   }
}

// class 키워드(ES6 문법) 사용
class Person{
	constructor(name){
    	this.name = name; // 속성

    }
    notice(){ // 메서드
		alert(this.name);
    }
}
  • 일반적인 다른 함수와 구분하기 위해 클래스는 보통 대문자로 시작하며 일반명사로 만들고 일반적인 함수는 적절한 동사를 포함하고 소문자로 시작한다.

  • this.name=name => this(만들어진 인스턴스에) name이라는 속성을 부여함

new 키워드 로 위에서 만든 클래스의 새로운 인스턴스를 만들면

let 혜린 = new Person('혜린')

두 코드의 실행을 통해 아래와 같은 결과가 나온다.

console.log(혜린.name) // 혜린

혜린.notice(); // alert가 발생 '혜린' 출력
  • 코드 실행을 통해 변수에 클래스의 설계를 가진 새로운 객체(인스턴스)가 할당되고,
  • 이렇게 만들어진 각각의 인스턴스는 클래스의 고유한 속성과 메서드를 갖는다.

용어 정리

  • prototype : 모델의 청사진을 만들 때 쓰는 원형 객체
  • constructor : 인스턴스가 초기화될 때 실행하는 생성자 함수
  • this : 함수가 실행될 때, 해당 scope 마다 생성되는 고유한 실행context
    new 키워드로 인스턴스를 생성했을 때는 해당 인스턴스가 바로 this의 값


private, protected

클래스의 필드는 public, private 두가지 타입으로 생성할 수 있는데
기본값은 public 으로 클래스의 내외부 어디서든 접근이 가능하다.

private 타입은 클래스 외부에서 접근할 수 없는 필드로
프로퍼티 이름 앞에 # 을 붙여 작성할 수 있다.

class User {
  name = "moon";
  #age = "secret";
  
  printAge() {
    console.log(this.#age);
  }
}

const newUser =  new User();

console.log(newUser.name); // moon
console.log(newUser.age); // undefined
newUser.printAge(); // secret

클래스 외부에서 private 설정한 프로퍼티에 접근할 수 없지만(undefined 노출)
클래스 내부에서 접근이 가능하기 때문에 printAge() 를 통해 사용 가능


static

인스턴스 없이 사용할 수 있는 프로퍼티나 메서드를 정적 프로퍼티, 메서드 라고 하고
static 키워드를 붙여 작성 가능
(클래스에서 프로퍼티와 메서드를 사용하기 위해 반드스 클래스를 인스턴스화(new) 해서 객체로 만들었는데, 이건 그 프로퍼티와 메서드가 클래스에 연결된 상태이기 때문)

class User {
	static hi() {
    	console.log('hi')
    }
}

User.hi();

⇒ 정적 프로퍼티와 메서드는 어떤 특정 객체에 속하는 것이 아니라 전체 클래스에 속하는 함수나 값을 구현할 때 주로 활용


extends 상속

기존의 클래스에 기능을 추가, 재정의 등 클래스를 확장하여 기존의 클래스를 기반으로 새로운 클래스를 만든다는 개념

class Car {
  type = 'car';

  greeting() {
  	console.log('hi')
  }
}

class Mini extends Car {
  brand = 'bmw'
}

const aBmwCar = new Mini();

console.log(aBmwCar.type); // car
console.log(aBmwCar.brand); // bmw
aBmwCar.greeting(); // hi

⇒ Car 클래스를 상속받은 Mini라는 새로운 클래스를 작성하고, Mini 클래스에 객체를 생성
클래스를 상속받을 때 extends 키워드를 사용하며, Mini 는 Car를 상속받아 type 과 greeting() 메서드에 접근할 수 있음


super() 생성자 오버라이딩

constructor(생성자 함수) 를 오버라이딩 할 때 부모의 생성자 함수를 호출하는
super() 를 호출해서 해결할 수 있다.
그러면 부모클래스의 constructor 와 오버라이딩한 constructor 가 모두 실행된다.
⇒ 부모, 자식 클래스의 생성자 함수가 순서대로 실행

만약 constructor 에서 인자를 요구한다면,
super() 에도 인자를 지정해 줘야 한다

class Car {
  constructor(name) {
  	this.name = name;
  }
}

class Mini extends Car {
  constructor(name, brand) {
  	super(name);
    this.brand = brand;
  }
}

const aBmwCar = new Mini('mini', 'bmw');

console.log(aBmwCar.name); // car
console.log(aBmwCar.brand); // bmw

0개의 댓글