[js] 객체 지향 프로그래밍

비트·2023년 5월 20일
0

JavaScript

목록 보기
11/22
post-thumbnail

객체 지향 프로그래밍

객체 지향적 프로그래밍 (Object Oriented Programming)은 데이터가 객체 내에 캡슐화되고 구성 요소 부분이 아닌 객체 자체가 운용되는 프로그래밍 방식.


new 연산자와 생성자 함수

new 연산자와 생성자 함수를 사용하면 유사한 객체 여러 개를 쉽게 만들 수 있다.


생성자 함수

생성자 함수(constructor function)와 일반 함수에 기술적인 차이는 없다.

  • 함수 이름의 첫 글자는 대문자로 시작.
  • 반드시 'new' 연산자를 붙여 실행.
function User(name) {
  this.name = name;
  this.isAdmin = false;
}

let user = new User("비트");

alert(user.name); // 비트
alert(user.isAdmin); // false

new User(...)를 써서 함수를 실행하면 아래와 같은 알고리즘이 동작

  1. 빈 객체를 만들어 this에 할당.
  2. 함수 본문을 실행. ( this에 새로운 프로퍼티를 추가해 this를 수정 )
  3. this를 반환

this 생성자 함수 해설

위 예시를 통해 this를 알아보자.

// new User(...)가 실행되면,

function User(name) {
  // this = {};  (빈 객체가 암시적으로 만들어짐)

  // 새로운 프로퍼티를 this에 추가함
  this.name = name;
  this.isAdmin = false;

  // return this;  (this가 암시적으로 반환됨)
}

이제 let user = new User("비트")는 아래 코드를 입력한 것과 동일하게 동작.

let user = {
  name: "비트",
  isAdmin: false
};

new User("비트")이외에도 손 쉽게 사용자 객체를 만들 수 있다.
객체 리터럴 문법으로 일일이 객체를 만드는 방법보다 간단하고 쉬우며, 재사용할 수 있는 객체 생성 코드를 구현한다.


new function() { … }

재사용할 필요가 없는 복잡한 객체를 만들어 보자.
익명 생성자 함수로 감싸주는 방식을 사용할 수 있다.

let user = new function() {
  this.name = "비트";
  this.isAdmin = false;

  // 사용자 객체를 만들기 위한 여러 코드.
  // 지역 변수, 복잡한 로직, 구문 등의
  // 다양한 코드가 여기에 들어간다.
};



Class

클래스는 객체 지향 프로그래밍에서 특정 객체를 생성하기 위해 변수와 메소드를 정의하는 일종의 틀로, 객체를 정의하기 위한 상태(멤버 변수)와 메서드(함수)로 구성된다.

class 선언은 프로토타입 기반 상속을 사용하여, 주어진 이름의 새로운 클래스를 만든다.


Class 기본문법

class MyClass {
  // 여러 메서드를 정의할 수 있음
  constructor() { ... }
  method1() { ... }
  method2() { ... }
  method3() { ... }
  ...
}
// 이렇게 클래스를 만들고, new MyClass()를 호출하면 
// 내부에서 정의한 메서드가 들어 있는 객체가 생성

객체의 기본 상태를 설정해주는 생성자 메서드 constructor()new에 의해 자동으로 호출되므로, 특별한 절차 없이 객체를 초기화 할 수 있다.

class User {

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

  sayHi() {
    alert(this.name);
  }

}

// 사용법:
let user = new User("비트");
user.sayHi(); // 비트

new User("비트")를 호출하면?

  1. 새로운 객체가 생성.
  2. 넘겨받은 인수와 함께 constructor가 자동으로 실행. (이때 인수 "비트"가 this.name에 할당)

이렇게 user.sayHi() 같은 객체 메서드를 호출할 수 있다.

메서드 사이엔 쉼표를 표기하지 않는다.

쉼표를 넣으면 문법 에러가 발생. 따라서, 클래스에선 메서드 사이에 쉼표를 넣지 않아도 된다.


Class는 함수일까?

자바스크립트에서 클래스는 함수의 한 종류이다.

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

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

class User {...} 문법 구조

  1. User라는 이름을 가진 함수를 만든다.
    • 함수 본문은 생성자 메서드 constructor에서 가져온다.
    • 만약 생성자 메서드가 없다면 본문이 비워진 채로 함수가 만들어진다.
  2. sayHi같은 클래스 내에서 정의한 메서드는 User.prototype에 저장

클래스 표현식

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

let User = class {
  sayHi() {
    alert("안녕하세요.");
  }
};

기명 함수 표현식 유사하게 클래스 표현식에도 이름을 붙일 수 있지만, 그럴 경우 오직 클래스 내부에서만 사용할 수 있다.

let User = class MyClass {
  sayHi() {
    alert(MyClass); // MyClass라는 이름은 오직 클래스 안에서만 사용할 수 있다.
  }
};

new User().sayHi(); // 원하는대로 MyClass의 정의를 보여준다.

alert(MyClass); 
// ReferenceError: MyClass is not defined, 
// MyClass는 클래스 밖에서 사용할 수 없다.

필요에 따라 클래스를 동적으로 생성하는 것도 가능하다.

function makeClass(phrase) {
  // 클래스를 선언하고 이를 반환함
  return class {
    sayHi() {
      alert(phrase);
    };
  };
}

// 새로운 클래스를 만듦
let User = makeClass("안녕하세요.");

new User().sayHi(); // 안녕하세요.

getter와 setter

리터럴을 사용해 만든 객체처럼 클래스도 gettersetter, 계산된 프로퍼티(computed property)를 지원한다.

class User {

  constructor(name) {
    // setter를 활성화합니다.
    this.name = name;
  }

  get name() {
    return this._name;
  }

  set name(value) {
    if (value.length < 4) {
      alert("이름이 너무 짧습니다.");
      return;
    }
    this._name = value;
  }

}

let user = new User("비트");
alert(user.name); // 비트

user = new User(""); // 이름이 너무 짧습니다.

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

클래스 필드

클래스 필드(class field)라는 문법을 사용하면 어떤 종류의 프로퍼티도 클래스에 추가할 수 있다.

class User {
  name = "비트";

  sayHi() {
    alert(`${this.name}님 안녕하세요!`);
  }
}

new User().sayHi(); // 비트님 안녕하세요!

클래스를 정의할 때 <프로퍼티 이름> = <값>을 써주면 간단히 클래스 필드를 만들 수 있다.

class User {
  name = "비트";
}

let user = new User();
alert(user.name); // 비트
alert(User.prototype.name); // undefined

// User.prototype가 아닌 개별 객체에만 클래스 필드가 설정된다.

클래스 필드엔 복잡한 표현식이나 함수 호출 결과를 사용 할 수 있다.

class User {
  name = prompt("이름을 알려주세요.", "비트");
}

let user = new User();
alert(user.name); // 비트



객체 지향 프로그래밍의 4가지 특징

1. 추상화 (Abstraction )

복잡하지 않게 만들고, 단순화된 사용으로 변화에 대한 영향을 최소화한다.

  • 내부 구현은 복잡하나 노출되는 부분은 단순하게 만드는 것.
    • 필요하지 않은 메서드등은 노출시키지 않고 단순한 이름으로 정의.

2. 상속 ( Inheritance )

불필요한 코드를 줄여 재사용성을 높인다.

  • 부모 클래스의 특징을 자식 클래스가 물려받는 것.
    • 기본 클래스(base class)의 특징을 파생 클래스(derived class)가 상속받는다

3. 다형성 ( Polymorphism )

동일한 메서드에 대해 if/else if와 같은 조건문 대신 객체의 특성에 맞게 달리 작성하는 것이 가능해진다.

  • 다양한 형태를 가지는 것.
    • 똑같은 메서드라도 다른 방식으로 구현 될 수 있다.

4. 캡슐화 (Encapsulation )

코드가 복잡하지 않게 만들고, 재사용성을 높인다.

  • 데이터(속석)와 기능(메서드)을 하나의 객체로 묶는 것.
    • 이러한 느슨한 결합이 되면, 언제든 구현을 수정할 수 있다.
  • 은닉화의 개념도 포함.
    • 은닉화 : 내부의 데이터나 구현이 외부로 노출되는 것을 숨기고, 동작은 노출 시킴.



프로토타입

JavaScript는 프로토타입(Prototype) 기반 언어

class Human {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }

  sleep() {
    console.log(`${this.name}은 잠에 들었습니다`);
  }
}

let kimcoding = new Human('김코딩', 30);

// 실습해보세요
Human.prototype.constructor === Human; 
Human.prototype === kimcoding.__proto__; 
Human.prototype.sleep === kimcoding.sleep;
// Human 클래스의 sleep 메서드는 프로토타입에 있으며, 
// Human 클래스의 인스턴스인 kimcoding에서 
// kimcoding.sleep으로 사용할 수 있다.

프로토타입 예제

프로토타입 예제 보러가기

profile
Drop the Bit!

0개의 댓글