OOP & OOP in JS


ch1. 객체

객체?

모든 것이 객체다!?

어떠한 사물 === Object.

현실세계를 인지하면서 프로그래밍을 하자!에서 출발

상상하고,볼 수 있고,만질 수 있는 것들은 모두 객체이다.

객체의 구성

모든 객체는 속성(property)과 행위(method)를 가질 수 있음.

  • 속성 : 사람의 키,나이,몸무게

  • 행위 : 움직이다, 먹다, 자다, 공부하다

people.eat();
people.getAddress();  //method~~~~
people.address;  //property

업계에서 현실적으로 사용되는 용어

  • 속성,필드,property는 같은말.

  • 함수,메서드도 같은말.

클래스와 객체

https://www.miltonmarketing.com/wp-content/uploads/2018/04/oopconceptimage15345345.png

class

어떠한 객체를 표현하기 위해, 일반화된 형태로 만든 것.

어떠한 집합이나 분류에 가깝다.(사람, 동물, 자동차 등)
추상적.

object(instance)

class를 통해서 얻을 수 있는 개별객체.

유일한 사물.

실체에 가깝다(crong, 사자, 벤츠)
구체적.

# OOP가 없었다면? 비슷한 형태의 자동차를 만드는 코드가 반복적으로 표현됐을것임. 객체지향을 통해서 이를 간단하고 효과 적으로 표현.

객체지향 관련 학습관계도

OOP 핵심 개념

객체지향 프로그래밍 언어에서 강조된 개념들.

  • Class

  • 캡슐화(Encapsulation)

  • 상속(Inheritance)

  • 다형성(polymorphism)

  • 추상화(abstraction)

OOP 핵심 개념 & JavaScript

1. Class

JavaScript는 class 없이 프로그래밍이 가능하다.
ES Classes는 ECMAScript 2015에서나 표준으로 등장. 그전에는 TypeScript 의 도움으로 사용.
생성자 함수와 prototype 속성을 통해서 클래스 형태를 구성할 수 있음.

2. 캡슐화(Encapsulation)

내부에서만 알고 있으면 될 것을, 외부에 공개하지 않는다. 필요한 것은 외부에 접근을 허용한다.

private, public 개념.
JavaScript도 이를 지원하고 있음.

module pattern을 통해서 이를 구현할 수도 있긴함.


3. 상속(Inheritance)

공통부분을 분리해서 재사용하려는 목적.

상위클래스와 하위클래스간에 연결을 짓는다.

  • 동동사람, BMW 자동차, 포크레인중장비, 아들 아빠(X)

  • kind of 관계.

prototype기반의 객체간 연결 chain을 통해 상속구조를 만들 수 있음.

child.prototype = Object.create(parent.prototype);

ES6 Class의 extends 키워드 역시 내부적으로는 결국 prototype을 통한 상속구조임.

4. 다형성(polymorphism)

다양한 성질로 동작하는 것.

overriding을 통한 재정의, overloading을 통한 메서드 중복정의.

JavaScript는 prototype chain내에 동일한 메서드를 두고 overriding구현은 가능.

하지만, interface가 없고, method overloading을 공식지원하지 않음

(다만,어떠한 타입을 체크해서, 다른 메서드를 호출해서 실행하도록 구현할 수는 있음)

JavaScript에 다형성이 존재하냐?는 중요한 논쟁거리는 아님.

오버로딩은 같은 클래스 내에서 메소드 이름은 같지만 매개변수가 다른 여러 메소드를 정의하는 것이고,
오버라이딩은 상속 관계에 있는 클래스에서 상위 클래스의 메소드를 하위 클래스가 재정의하는 것.


5. 추상화(abstraction)

필요한 부분만을 선택해서 클래스를 만드는 것.

‘차’는 ‘버스’클래스와 ‘중장비’클래스로 구분지을 수 있는데, 버스와 중장비는 서로 다른 속성과 행위가 필요하다. 이렇게 필요한 부분을 선택해서 클래스를 만들 수 있고, 이를 추상화라고 함.

JavaScript에서도 이를 표현하는건 당연히 가능!

CH2. JS 객체 표현방법

프론트엔드에서는 OOP를 ?

1. object literal

class없이 바로 object로 표현가능(singleton)

var healthObj = {
  name : "달리기",
  lastTime : "PM10:12",
  showHealth : function() {
    console.log(this.name + "님, 오늘은 " + this.lastTime + "에 운동을 하셨네요");
  }
}

healthObj.showHealth();

2. Class - ES6

class를 에서 제공하는 constructor라는 생성자가 주어짐. class를 호출하면 constructor가 자동호출 됨.

constructor는 instance를 만들어서 반환. 다시말해 객체(instance)를 생성해서 반환.

class Health{
  constructor(name,healthTime) {
    this.name = name;
    this.healthTime = healthTime;
  }

  showHealth(){
     console.log(this.name + "님, 오늘은 " + this.healthTime + "에 운동을 하셨네요");
  }

}

const ho = new Health("crong", "12:12");
ho.showHealth();

https://caniuse.com/#feat=es6-class

3. Class - ES3

function을 new 키워드로 호출하면, 그 함수는 constructor가 됨.

const Health = function(name,healthTime) {
  this.name = name;
  this.healthTime = healthTime;
  this.showHealth = function() {
    console.log(this.name + "님, 오늘은 " + this.healthTime + "에 운동을 하셨네요");
  }
}

const ho = new Health("crong", "12:12");
ho.showHealth();

4. Prototype object - ES3

function Health(name, healthTime) {
  this.name = name;
  this.healthTime = healthTime;
}

Health.prototype.showHealth = function() {
  console.log(this.name + "님, 오늘은 " + this.healthTime + "에 운동을 하셨네요");
}

const ho = new Health("crong", "12:12");
ho.showHealth();

5. Object.create - ES5

Object.create는 직접적으로 prototype키워드를 사용하진 않지만, Prototype object를 만드는 것과 동일.

const healthObj = {
  showHealth : function() {
    console.log(this.name + "님, 오늘은 " + this.healthTime + "에 운동을 하셨네요");
  }
}

const ho = Object.create(healthObj, {
   name: { value: "crong" },
   healthTime: { value: "12:22" } 
})

ho.showHealth();

Object.create는 prototype기반 상속을 좀더 매끄럽게 사용하기 위해 탄생했다고 이해할 수 있음.

Object.create를 사용하면 상속구조가 잘 만들어짐. 하지만 ES6 Classes의 extend를 사용해서 이제 보다 쉽게 클래스간 상속 구조를 만들 수 있게 됨.

object literal vs. class

1. object literal

여러개의 객체를 만들어서 생성할 필요가 없을때, 즉 일반화할 필요가 없는 경우에는 단순히 object literal로 객체를 표현.

2. class

하나 이상으로 개별적인 객체를 생성해야 할 때.

타입스크립트란?

1. TypeScript vs. JavaScript

1.1 Typescript

TypeScript는 Microsoft사가 JavaScript를 확장해서 만든 언어이다.(superset)

따라서 JavaScript 문법을 그대로 다 사용할 수 있으며, 추가로 사용할 수 있는 강력한 문법들을 제공한다.

1.2 JavaScript 코드

class Cat {
    constructor(name) {
        this.name = name;
    }
    jump() {
        console.log('살금살금 점프');
    }
    sleep(time) {
        setTimeout(() => console.log('zzzZZ.'), time);
    }
    getName() {
        return this.name;
    }
}

1.3. TypeScript 코드

class Cat {
    private name: string;

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

    jump(): void {
        console.log('살금살금 점프')
    }

    sleep(time: number): void {
        setTimeout(() => console.log('zzzZZ.'), time);
    }

    getName(): string {
        return this.name;
    }
}

1.4 TypeScript의 구성

  • 소스코드

  • 타입 검사기

  • 컴파일러

  • 타입 정의 파일

1.5 설치와 확인

1.5.1 설치

yarn global add typescript
tsc --init

1.5.2 실행

tsc practice.ts 
node practice.js

1.5.2 Online

TypeScript Playground


2. JavaScript & TypeScript Types

2.1 JavaScript의 타입

string, boolean, number, bigint, symbol, null, undefined

function, array, object, RegExp, Date ..

2.2 TypeScript에 더 있는 타입들

Tuple, Enum, Any, Void, Never, Unions, unknown

2.3 Static Typing

JavaScript의 type은 동적으로 결정되는 특징을 가진 dynamic typing(동적타이핑) 언어다.

TypeScript에서는 정적타이핑을 목적으로 하고 있다. 다시 말해 코드에 타입을 명시적으로 선언하고 그에 맞는 값을 할당해야 한다.

이렇게 추가된 타입 선언은 런타임 단계에서 문제가 발생하는 것이 아니고, 개발 중에 IDE를 통해서 쉽게 정적인 에러를 발견할 수가 있다. 이 부분은 TypeScript의 큰 장점이다.

2.4 타입 시스템

타입 시스템은 아래와 같은 단계로 타입에 오류가 있는지를 확인.

// 오류가 있는 코드임
const crong = "crong crong";
crong.forEach();
  1. 코드를 분석해서 타입과 값을 이해 (crong이 있군)

  2. 각 값의 타입을 확인 (crong은 문자열이군)

  3. 각 값이 어떻게 사용할 수 있는지 방법 확인(crong에 forEach는 없는데…)

  4. 오류 표시 (“Property ‘forEach’ does not exist on type ‘string’”)

진단과 분석(프로파일링)

  • 퍼포먼스(수행 과정에 대한 녹화하고 진단)
  • 개발자 도구(lighthouse)
  • 로딩 타이밍에 빠른 화면 노출과 빠른 반응 노출

테스트

  • ete 테스트(end-to-end 테스트)