🧡 객체 지향
- 데이터와 기능을 한 곳에 묶어서 처리합니다. 속성과 메서드가 하나의 '객체'라는 개념에 포함되며, 내장타입인 object와 다르게 class라는 이름으로 부릅니다.
- 각 객체는 별도의 역할을 가지는 독립적인 기계 또는 부품으로 볼 수 있으며, 객체간에 데이터를 처리하고 메시지를 주고 받을 수도 있습니다.
- 객체지향 모델링은 실제세계에 존재하고 인지하고 있는 객체를 중심으로 '누가 어떤 일을 할 것인가?'를 핵심으로 객체의 역할을 정의해 나가는 것에 초점을 맞춥니다.
🎀 절차 지향 프로그래밍
객체 지향 프로그래밍 등장하기 전, 프로그램을 기능중심으로 바라보는 방식으로 '무엇을 어떤 절차로 할 것인가?'를 핵심으로 기능을 어떤 순서로 처리할 지에 초점을 맞추었습니다.
💚 클로저와 모듈패턴
-
메서드 호출은 객체.메서드()
객체 내에 메서드를 호출하는 방법을 의미합니다. 메서드 호출 방식을 이용할 때에는 화살표 함수를 쓰지 않습니다.
-
단순 객체를 사용해 호출하는 경우, 재사용성이 떨어지는 단점이 있습니다.
let counter = {
value : 0;
increase : function () {
this.value++;
}}
counter.increse()
counter.increse()
- 똑같은 기능을 하는 카운터를 여러 개 만드는 방법 중 하나로 클로저 모듈 패턴을 이용할 수 있습니다.
function counter() {
let value = 0;
return {
increase : function(0 {
value ++ ;
}}}
let counter1 = counter()
counter1.increase ()
let counter2 = counter()
counter2.increase()
💚 클래스와 인스턴스
classes : class는 객체를 생성하기 위한 템플릿입니다. 데이터와 이를 조작하는 코드를 하나로 추상화합니다. 클래스를 호출하면서 전달인자를 통해 속성의 값을 동적으로 설정해 줄 수 있습니다.
인스턴스
- 클래스에 세부사항을 넣으면 객체가 됩니다. 이 세부사항을 넣어주는 역할이 바로 생성자입니다. 생성자를 통해 세부사항을 넣어줍니다. 함수에 인자를 넣듯 속성을 넣을 수 있습니다.
- 생성자 함수와 new 연산자를 통해 인스턴스를 생성할 수 있습니다. 이때 생성자 함수는 클래스이자 생성자의 역할을 합니다.
클래스 정의
- class 선언 : class 키워드를 사용하 선언하는 것입니다. 함수와 다르게 클래스는 호이스팅될 때 초기화되지 않기 때문에 반드시 정의한 뒤에 사용할 수 있습니다.
class Rectangle {
constructor(heigth, width) {
this.height = heigth;
this.width = width;
}
}
- class 표현식 : 이름을 가질 수도 있고, 가지지 않을 수도 있습니다. 이름을 가진 class 표현식은 body의 local scope에 한해 유효합니다. 하지만 인스턴스 이름이 아닌 name속성으로 찾을 수 있습니다.
let Rectangle = class {
constructor(height, width) { ... }
}
let Rectangle = class Rctangle2 {
constructor(height, width) { ...}
}
- 객체 지향 프로그래밍 : 하나의 모델이 되는 청사진(설계도)을 만들고, 청사진을 바탕으로 한 객체를 만드는 프로그래밍 패턴입니다. 이 때의 청사진을 클래스라고 부르고, 이를 바탕으로 한 객체는 (그냥 객체가 아니라) 인스턴스 객체라고 부릅니다.
- 객체는 함수를 정의하듯 만듭니다. 다만 함수와 다르게 그냥 실행하는 것이 아니고 new 키워드를 써서 만듭니다. 이는 새로운 인스턴스를 만드는 방법입니다.
- 일반적인 다른 함수와 구분하기 위해 클래스는 보통 대문자로 시작하며 일반 명사로 만듭니다. (일반적인 함수는 동사를 포함하고 소문자로 만듭니다.)
- ES5에서 사용되는 함수는 객체지향프로그래밍에서 생성자 함수라고 부르고, 생성자 함수는 return값을 만들지 않습니다. ES6에서는 클래스를 만드는 새로운 문법(class 키워드)가 새로 도입되었습니다.
🎀 ES5 vs ES6에서의 클래스 정의
function car(brand, name, color) {
}
class Car {
constructor(brand, name, color) {
}
- 인스턴스를 만들 때 new키워드를 사용합니다. 즉시 생성자 함수가 실행되며, 변수에 클래서의 설계를 가진 새로운 객체, 즉 인스턴스가 할당됩니다. 각 인스턴스는 클래스의 고유한 속성과 메서드를 가지게 됩니다.
let beetles = new Car('volkswagen', 'beetles', 'yello');
- 클래스에 속성과 메서드를 정의하고 인스턴스에서 이용합니다. 메서드는 객체에 딸린 함수입니다.
prototype
이라는 키워드를 사용해 메서드를 정의할 수 있습니다. ES6에서는 생성자함수와 함께 class 키워드 안쪽에 묶어서 정의합니다.
Car.prototype.drive = function() {
class Car {
drive () {
}
- 설정한 속성과 메서드는 인스턴스에서 사용할 수 있습니다.
let beetles = new Car (...);
beetles.dirve();
🎀 prototype - constructor - this
- prototype : 모델의 청사진을 만들 때 쓰는 원형 객체 입니다.
- constructor : 인스턴스가 초기활 될 때 실행하는 생성자 함수입니다.
- this : 함수가 실행될 때, 해당 scope 마다 생성되는 고유한 실행context 입니다. new 키워드로 인스턴스를 생성했을 때에는 해당 인스턴스가 바로 this가 됩니다.
🧡 객체지향 프로그래밍
- 순차적 작동을 넘어 데이터의 접근과, 데이터의 처리 과정에 대한 모형을 만들어 내는 방식을 고안했습니다. 즉 데이터와 기능을 별개로 취급하지 않고 한 개로 묶어서 처리하게 되어었습니다. 클래스라고 부르는 데이터 모델의 청사진을 사용해 코드를 작성하며, 현대의 언어들은 대부분 객체지향의 특징을 가지고 있고, 자바스크립트는 객체지향언어는 아니지만 객체지향패턴으로 작성할 수 있습니다.
💚 OPP
- 프로그램 설계 철학 중 하나입니다. 객체로 그룹화되는데, 이 객체는 한 번 만들고 나면, 메모리상에서 반환되기 전까지 객체 내의 모든것이 유지됩니다.
OPP Basic Concepts
🎀 객체 지향 프로그래밍은 크게 네 가지의 기본 개념이 있습니다.
- Encapsulation (캡슐화) : 코드가 복잡하지 않게 만들고, 재사용성을 높입니다.
- Inheritance (상속) : 불필요한 코드를 줄여 재사용성을 높입니다.
- Abstraction (추상화) : 코드가 복잡하지 않게 만들고 단순화된 사용으로 변화에 대한 영향을 최소화합니다.
- Polymorhpism (다형성) : 동일한 메서드에 대해 조건문 대신 객체 특성에 맞게 달리 작성하는 것이 가능합니다.
Encapsulation 캡슐화
- 객체가 독립적으로 역할할 수 있도록 이터(속성)와 기능(메서드)를 느슨하게 하나로 묶어 관리하는 것입니다. 코드가 묶여있어서 상대적으로 오류가 없어 편리합니다. 느슨한 결합 코드는 코드가 상징하는 실제 모습과 닮게 코드를 모아 결합하는 것을 의미합니다.
- 캡슐화에는 '은닉화' 특징도 포함하는데, 은닉화는 내부 데이터나 내부 구현이 외부로 노출되지 않도록 만드는 것입니다. 디테일한 구현이나 데이터는 숨기고, 객체 외부에서 필요한 동작(메서드)만 노출시켜야 합니다. 이러한 특징을 살리면 객체 내 메서드의 구현만 수정하고 노출된 메서드를 사용하는 코드 흐름은 바뀌지 않도록 만들 수 있습니다.
🎀 vs. 절차적 코드의 경우
데이터의 형태가 바뀔 때에 코드의 흐름에 큰 영향을 미쳐 유지보수가 어렵습니다.
- 데이터를 보이지 않고 외부와 상호작용 할 때에는 메소드를 이용하여 통신을 합니다. 보통 라이브러리로 만들어 업그레이드 해 사용합니다.
Abstraction 추상화
- 객체들의 공통적인 특징(기능, 속성)을 도출하는 것입니다 객체지향적 관점에서 클래스를 정의하는 것을 추상화라고 할 수 있습니다.
- 내부 구현은 복잡하지만 실제 노출되는 부분은 단순하게 만든다는 개념입니다. 추상화를 통해 인터페이스를 단순화하면 너무 많은 기능이 노출되지 않아 의도하지 않은 사용상 변화를 막을 수 있습니다.
Ingeritance
- 하나의 클래스가 가진 특징(함수, 데이터)를 다른 클래스가 상속받는 것으로 기본 클래스(부모 클래스)의 특징을 파생클래스(자식 클래스)가 상속받습니다.
- 부모클래스는 이미 작성된 클래스이고 이를 새로운 클래스를 생성(자식 클래스)하는 것입니다. 기존 코드를 재사용하는 중요한 기능입니다.
Polymorphism
- 조금씩 다른 방식으로 동작하는 함수를 동일한 이름으로 호출하는 것입니다. 공통되는 부모 클래스에 메서드를 만들고 상속을 받는 경우, 똑같은 메서드라도 자식 클래서에서 다 조금씩 다른 방식으로 구현되고 작동될 수 있습니다.
- 이러한 다형성이 없다면 부모클래스에 하나하나 다르게 만들어야하고, 각 자식 클래스에 별도로 다른 함수를 만들어야 합니다.
🎀 오버라이딩과 오버로딩
- 오버라이딩(Overriding) : 부모클래스의 메소드와 같은 이름을 사용하며 매개변수도 같되 내부 소스를 재정의하는 것입니다.
- 오버로딩(Overloading) : 같은 이름의 함수를 여러 개 정의한 후 매개변수를 다르게 하여 같은 이름을 경우에 따라 호출하여 사용하는 것입니다.
객체지향 프로그래밍의 장점
- 소프트웨어의 재사용을 지향합니다. 상속받거나 재사용, 부분수정 등을 통해 소프트웨어를 작성하는 부담을 줄입니다.
- 개발자가 만든 데이터를 사용하기 때문에 신뢰성 있는 소프트웨어를 작성할 수 있습니다.
- 코드의 재사용, 업그레이드, 디버깅이 쉽습니다.
- 캡슐화를 통해 실제로 구현되는 부분을 은닉하여 보안성이 높아집니다.
객체지향 프로그래밍의 단점
- 캡술화와 격리구조 때문에 실행속도가 절차지향에 비해 느립니다. 또 모든것을 객체로 생각하기 때문에 추가적인 포인터 크기의 메모리와 연산에 대한 비용이 들어갑니다.
💚 객체지향 TypeScript과 비교
은닉화의 한계 (private 키워드)
- 자바, 타입스크립트 언어는 클래스 내부에서만 쓰이는 속성 및 메서드를 구분시키기 위해 private키워드를 제공합니다. 이러한 은닉화를 도와주는 기능이 자바스크립트에는 널리 쓰이지 않습니다(지원하는 브라우저가 적습니다).
- 자바스크립트에서는 은닉화를 위해 '클로저 모듈 패턴'을 사용합니다.
추상화 기능의 부재(interface 키워드)
- 추상화는 인터페이스의 단순화를 의미합니다. 자바나 타입스크립트 언어는 주요 기능으로 추상화를 구현해 놓았지만, 자바스크립트에는 존재하지 않습니다.
- 인터페이스는 일종의 규약처럼 간주되어, 인터페이스를 클래스로 구현하는 사람들이 이에 맞게 작성하도록 돕습니다. 클래스를 이용하는 입장에서는 노출된 인터페이스를 통해 '메서드 이름이 의도한 바대로 작동할 것이다'라는 것을 명백히 드러나게 해줍니다. 또 실질적인 구현방법을 공개하지 않고 사용법을 노출시키기에도 유리합니다.
- 어떤 클래스가 외부공개용으로 모듈처럼 작동할 때 인터페이스가 빛을 발하는데 이러한 대표적인 예가 API입니다.
🧡 프로토타입
자바스크립트는 프로토타입 기반 언어입니다. 프로토타입은 원형객체를 의미합니다.
- 자바스크립트의 모든 객체는 부모객체의 프로퍼티 또는 메소드를 상속받아 사용할 수 있고, 이런 부모역할의 객체와 연결되어 있습니다. 이러한 부모객체를 프로토타입객체(프로토타입)이라고 합니다.
- 프로토타입 객체는 생성자 함수에 의해 생성된 각 객체에 공유 프로퍼티를 제공하기 위해 사용합니다.
-
[[프로토타입]]의 값은 프로토타입 객체이고, __proto__
accessor property로 접근할 수 있고, 접근시에 객체를 반환합니다.
-
클래스와 인스턴스, 프로토타입의 관계는 Array(배열)의 원리와 유사합니다. 배열은 Array 클래스의 인스턴스이며, 프로토타입으로 다양한 메서드가 존재합니다.
💚 프로토타입 체인
프로토타입 기반 객체지향 프로그래밍에서 객체들이 상속받는 프로퍼티와 메서드를 찾는 과정을 말합니다. 객체는 프로토타입을 기반으로 생성되며, 프로토타입에 정의된 프로퍼티와 메서드를 상속받습니다. 그리고 프로토타입은 다시 다른 프로토타입을 상속받을 수 있습니다. 객체는 자신의 프로퍼티와 메서드를 찾을 때, 프로토타입 체인을 타고 올라가며 프로퍼티와 메서드르 찾습니다. 이를 통해 객체들은 서로 다른 상태를 가지면서도 공통적인 행동을 할 수 있게 됩니다.
-
속성과 메서드를 물려주는 상속을 자바스크립트에서 구현할 때 프로토타입 체인을 사용합니다.
-
브라우저에서 DOM을 이용하면, document.createElement('div')로 새로운 div엘리먼트를 만들 수 있습니다. 이렇게 생성된 엘리먼트는 HTMLDivElement라는 클래스의 인스턴스입니다.
-
DOM 엘리먼트는 innerHTML, append() 같은 메서드나 속성을 통해 Element라는 공통의 부모가 있음을 알 수 있습니다.
-
모든 클래스의 조상은 Object로 귀결됩니다.
-
__proto__
를 이용해 부모클래스의 프로토타입, 혹은 부모의 부모 클래스의 프로토타입을 탐색할 수 있습니다
-
.prototype 프로퍼티는 그 함수로 생성되는 객체들이 상속받을 프로퍼티와 메서드를 정의할 수 있는 객체를 가리킵니다.