JavaScript - 클래스와 인스턴스

Kim-DaHam·2023년 3월 15일
0

JavaScript

목록 보기
9/18
post-thumbnail

🔥 학습목표

  • 클로저 모듈 패턴에 대해 설명할 수 있다.
  • 클래스와 인스턴스에 대해 설명할 수 있다.
  • 자바스크립트 DeepDive 25장을 학습한다.
  • '한 번 읽으면 두 번 깨닫는 객체지향 프로그래밍'을 복습한다.



🟩 클로저 모듈 패턴

🟣 먼저 알고있어야 할 개념

⬜ 즉시 실행 함수

(IIEE, Immediately Invoked Function Expression)
함수 정의와 동시에 즉시 호출되는 함수. 단 한 번만 호출되며 다시 호출할 수 없다.

(function () {
 let a = 3;
 let b = 6;
 return a * b;
}());
  • 함수 이름이 없는 익명 함수를 사용하는 것이 일반적이다.
  • 반드시 괄호()로 감싸야 한다.
    • 무명 함수를 ()로 감싸면 함수 리터럴로 평가 되어 함수 객체가 된다.
    • 모든 변수는 즉시 실행 함수의 지역변수가 된다.
    • 즉, 외부에서는 접근 불가능한 독립적인 스코프를 가진다.
    • 이를 활용하여 전역변수의 사용을 제한한다.
  • 즉시 실행 함수에 코드를 모아 두면 변수나 함수의 중복 충돌을 방지할 수 있다.

⬜ 네임스페이스 패턴

네임 스페이스란?
└▷ 구분이 가능하도록 정해놓은 범위나 영역.
==▶ 객체나 변수가 겹치지 않는 안전한 소스코드를 만들자는 개념으로 사용 된다.

< 자바 스크립트의 전역변수(전역 네임스페이스) 단점>

  • 변수명이 겹칠 수 있다.
  • 어디서든 접근 가능해서 신뢰성이 떨어진다.

<네임 스페이스 패턴이란?>

전역 범위에 다양한 함수, 객체, 변수들로 어지럽히지 않고, 단 하나의 전역 객체를 만든 뒤 모든 기능을 이 객체에 추가하는 패턴이다.
(더 자세한 네임스페이스 패턴의 종류는 후에 학습한다.)


아래 코드에는 생성자 함수 2개, 변수 1개, 객체 1개,
총 4 개의 전역변수가 존재한다.

function parent() {}
function child() {}

var var1 = 1;
var object = {
  data: { a:1, b:2 },
  // ...
};

이를 전역 객체에 넣어 네임 스페이스 패턴을 사용하면 다음과 같이 바뀐다.

var MyApp = {};

// constructor
MyApp.parent = function() {};
MyApp.child = function() {};

// 변수
MyApp.var1 = 1;
// 객체
MyApp.object = {
  //...
};

(코드의 가독성을 위해 객체 이름은 모두 대문자로 쓴다.)

< 차이점 >

  • 계층적 의미에 맞춰 기능들을 그룹화 한다.
  • 해당 기능을 어디에서 호출하는지 알게 된다.

⬜ private / public 멤버

  • private : 외부에서 접근 불가능한 변수. 접근 메소드를 따로 정의해줘야 한다.
  • public : 외부에서 접근 가능한 변수.

⬜ 의존관계 선언 패턴

의존 관계란?
하나의 객체가 다르 객체에게 의존성을 제공하는 것. 부모, 자식과 같다.

ex) A 객체에서 B 객체의 기능을 필요로 하는 경우 의존 관계다.

예를들면, dom은 지역이고 window.document 는 전역이다. domwindow.document에 의존한다.

var dom = window.document;
var loc = window.location;

< 의존 관계를 선언해야 하는 이유 >

  • 의존 관계가 명시적으로 선언 되어있어야 코드 분석이 쉽다.
  • dom 과 같은 지역 변수는 window.document 전역변수에 계속 접근하는 것보다 훨씬 빠르다. 되도록 전역 객체 판별은 한 번만 하는 게 좋다.

⬜ 클로저

함수와 그 함수가 접근할 수 있는 변수의 조합

[S1U9] 에서 보았 듯이 클로저란

이미 실행 종료 된 함수의 "변수나 함수를 참조"할 수 있는 내부 함수를 뜻한다.

이러한 참조 범위, <스코프>를 활용해서 변수의 접근 범위를 닫을 수 있는 게 클로저의 핵심 기능이다.



🟣 모듈 패턴이란

⬜ 모듈 패턴의 정의

위에서 설명한 네 가지 패턴을 조합한 게 모듈 패턴이다.

  • 네임 스페이스 패턴
  • 즉시 실행 함수
  • private / public 멤버
  • 의존 관계 선언

└▶ 오직 내부 함수에서만 접근 가능한 클로져의 특성을 이용해 이러한 모듈 패턴을 구현하 것이다.


⬜ 모듈 패턴을 사용하는 이유

  • 간결하고 재사용성이 좋다.
  • 전역변수를 줄임으로써 변수를 보호할 수 있다.

예를 들어, 아래와 같이 exercise라는 객체가 있다.

let exercise1 = {
  minute: 0,
  increseMin: function() {
    this.minute += 30;
  },
  getMinute: function(){
      return this.minute;
  }
}

exercise1.increaseMin();
exercise1.increaseCal();

만약 운동 한 종류를 했을 때 위와 같이 객체의 값을 조정할 수 있다.

하지만 다양한 운동을 하게 됐을 땐 어떡할까?
exercise1 객체는 자기자신 단 하나의 객체일 뿐이다.

따라서 똑같이 시간을 기록해야하는 다른 운동을 해야할 경우, 같은 내용의 또다른 객체를 하나 더 만들어야 한다.

즉 재사용성이 떨어진다.

이러한 단점을 보완하려면 클로저를 사용해 매번 같은 내용의 새로운 객체를 만들도록 해야 한다.

function doExercise() {
  let minute: 0;
  return {
  	increseMin: function() {
    	minute += 30;
  	},
    getMinute: function(){
      return minute;
    }
  }
}

let running = doExercise();
running.increaseMin();
running.getMinute(); // 30
let personalTraining = doExercise();
personalTraining.increaseMin();
personalTraining.increaseMin();
personalTraining.getMinute(); // 60

이렇게 "운동" 이라는 똑같은 기능을 하는 runningpersonalTraining을 따로 생성하여 분리할 수 있는 것이다.




🟩 클래스와 인스턴스

'한 번 읽으면 두 번 깨닫는 객체지향 프로그래밍' 도서 참고

  • 클래스 : 일종의 원형(original form). 객체를 생성하기 위한 원본 고정틀이다.
  • 인스턴스 : 클래스라는 틀로 찍어낸 사례이다.
  • 생성자 함수 : 클래스가 갖고 있는 '객체를 만들기 위한 함수' 이다. 속성들을 초기화 한다.

즉, 클래스란 코드로 작성한 설계도이며, 클래스 코드를 바탕으로 실제로 생성해 메모리에 올라가면 객체가 된다.

클래스 = 추상적
객체화 = 객체 = 구체적

이라고 볼 수 있다.


🟣 객체 지향 프로그래밍

⬜ 객체란?

상태 데이터(프로퍼티)와 동작(메서드)를 하나의 논리적인 단위로 묶은 복합적인 자료구조


⬜ 객체 지향 프로그래밍이란?

독립적인 객체의 집합으로 프로그램을 표현하려는 프로그래밍 패러다임


⬜ 자바스크립트에서의 객체지향

자바스크립트는 프로토타입 기반(prototype based) 객체지향 언어다.

프로토타입 객체 지향 언어란?
└▶ 클래스가 필요 없는(class free) 객체지향 프로그래밍 언어다.


ES5에서의 객체지향 언어

  • 생성자 함수프로토타입을 통해 객체지향 언어의 상속을 구현할 수 있다.

이렇게 함수로 정의할 수 있다.

var Person = (Function () { // 즉시 실행 함수(함수 객체 생성을 위해)
	// 생성자 함수
    function Person(name) {
  		this.name = name;
	}
	// 프로토타입 메서드
	Person.prototype.sayHi = function() {
      console.log('bla bla');
    };
	// 생성자 함수 반환
	return Person;
}());

// 인스턴스 생성
var me = new Person('Lee');
me.sayHi();
                    

그러나 이러한 프로토타입 기반 프로그래밍 방식은
기존 클래스 기반 언어에 익숙한 프로그래머들에게 혼란을 가져다 주었다.

따라서,

ES6에서 도입된 클래스클래스 기반 객채지향 프로그래밍 언어와 매우 흡사한 새로운 객체 생성 매커니즘을 제시한다.


ES6에서의 객체지향 언어

  • class라는 키워드를 이용해서 정의할 '수도' 있다.
class Person {
	// 생성자 함수 (인스턴스 생성 및 초기화)
   	constructor(name) {
  		this.name = name;
	}
	// 프로토타입 메서드
	sayHi() {
      console.log();
    };
	// 정적 메서드(인스턴스를 생성하지 않아도 호출할 수 있는 메서드)
	static sayHello(){
      console.log();
    }
}

// 인스턴스 생성
const me = new Person('Lee');
me.sayHi();
                    

그러나 사실 클래스는 함수이며 기존 프로토타입 기반 패턴을 클래스 기반 패턴처럼 사용할 수 있도록 만들었을 뿐이다.

  • 클래스와 생성자 함수 모두 프로토타입 기반의 인스턴스를 생성한다.
  • 그러나 동일하게 동작하지는 않는다.
  • 클래스는 생성자 함수보다 엄격하며 생성자 함수에서 제공하지 않는 기능도 제공한다.



🟣 클래스

⬜ 용어 정의

  • prototype : 원형 객체(original form). 인스턴스들의 원본 같은 것.
  • constructor : 인스턴스가 초기화 될 때 실행하는 생성자 함수
  • this : 함수가 실행될 때 해당 scope 마다 생성되는 고유한 실행 context. new 키워드로 인스턴스를 생성하면 해당 인스턴스가 바로 this의 값이 된다.

⬜ 클래스 정의

  • ES5
function Car(brand, name, color) {
  // 인스턴스가 만들어질 때 실행되는 코드
}
  • ES6
class Car {
  constructor(brand, name, color){
    // 인스턴스가 만들어질 때 실행되는 코드
  }
}

  • 인스턴스 만들기 : new 키워드를 통해 만들 수 있다.
let avante = new Car('hyundai', 'avante', 'black');

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


⬜ 속성 정의

  • ES5
function Car(brand, name, color) {
  this.brand = brand;
  this.name = name;
  this.color = color;
}
  • ES6
class Car {
  constructor(brand, name, color){
    this.brand = brand;
    this.name = name;
    this.color = color;
  }
}

⬜ 메서드 정의

  • ES5
function Car(brand, name, color) { /*생략*/ }

Car.prototype.fefuel = function() {
  // 연료 공급을 구현하는 코드
}
  • ES6
class Car {
  constructor(brand, name, color){ /*생략*/ }
  
  refuel() {
    // 마찬가지
  }
}



🟣 인스턴스

⬜ 인스턴스 생성 및 사용

인스턴스에서의 사용법은 ES5와 ES6가 똑같다.

let mini = newCar('bmw', 'mini', 'white');
mini.brand; // 'bmw'
mini.refuel(); // 연료를 공급한다.



profile
다 하자

0개의 댓글