자바스크립트는 객체 기반의 프로그래밍 언어이며,
자바스크립트를 이루고 있는 거의 '모든 것'이 객체다.
그말은 즉, 원시타입의 값을 제외한 나머지 값들(함수, 배열, 정규 표현식 등)은 모두 객체
객체는 상태 데이터와 동작을 하나의 논리적인 단위로 묶은 복합적인 자료구조
이때 객체의 상태 데이터를 프로퍼티, 동작을 메서드라고 부른다
객체지향 프로그래밍
객체지향 프로그래밍의 정의는 이러하다.
객체 지향 프로그래밍은 컴퓨터 프로그래밍 패러다임 중 하나로,
프로그래밍에서 필요한 데이터를 추상화시켜 상태와 행위를 가진 객체를 만들고
그 객체들 간의 유기적인 상호작용을 통해 로직을 구성
그래서 뭐라고...?? 뭐해서 뭐하다고? 쉽게 설명 해.줘.
일단 단어부터 바꿔보자 객체는 너무 어려운말이다. 객체를 "사물" 이라고 생각하자
실제로 우리가 사물을 바라보는 관점, 그 사물들의 연계성을 생각하는 관점
이것들을 프로그래밍에 적용하여 모델링하는 패러다임이라 생각.
클래스 : 일종의 원형(original form)으로, 객체를 생성하기 위한 아이디어나 청사진
인스턴스 : 클래스의 사례
예를 들어, 자동차 생산을 위한 설계도를 보면,
자동차가 기능하기 위해 네 바퀴와 핸들, 좌석 그리고 엔진이 필요함.
이런 기본적인 설계는 차의 종류와 상관없이 대체적으로 동일
이런 설계도를 통해 각각의 객체가 특정한 자동차 모델로 나오게 되는것.
여기서 설계도를 클래스(class) , 자동차모델을 인스턴스(instance)라고 부른다.
ES5 문법에서는 클래스를 함수로 정의를 했었다.
function Car(brand, name, color){
// 인스턴스가 만들어질 때 실행되는 코드
}
하지만, ES6 문법에서는 클래스를 class라는 키워드를 사용하여 생성자함수를 정의한다.
생성자 함수는 return값을 만들지 않는다
class Car {
constructor(brand, name, color) {
// 인스턴스가 만들어질 때 실행되는 코드
}
}
클래스의 속성을 정의할때도 ES5 와 ES6의 차이가 있다.
ES5 문법은 아래와 같이 Car 클래스의 속성을 정의했지만
function Car(brand, name, color){
this.brand = brand;
this.name = name;
this.color = color;
}
ES6 문법에서는 아래와 같이 Car 클래스의 속성을 정의한다.
class Car {
constructor(brand, name, color) {
this.brand = brand;
this.name = name;
this.color = color;
}
}
클래스의 메서드를 정의할때도 속성과 마찬가지로 ES5와 ES6에서의 차이가 있다.
ES5에서는 아래와 같이 메서드를 정의했다.
function Car(brand, name, color) { /* 생략 */}
Car.prototype.refuel = function() {
// 연료 공급을 구현하는 코드
}
Car.prototype.drive = function() {
// 운전을 구현하는 코드
}
하지만 ES6 에서는 메서드를 이렇게 정의한다.
class Car{
constructor(brand, name, color) { /* 생략 */ }
refuel(){
}
drive(){
}
}
인스턴스는 new 키워드를 통하여 만든다.
let avante=new Car('hyundai','avante','black');
let mini=new Car('bmw','mini','white');
let beetles=new Car('volkswagen','beetles','red');
여기서 각각의 인스턴스(avante, mini, beetles)는 Car라는 클래스의 고유한 속성과, 메소드를 갖는다.
위의 내용으로 ES6 문법으로 코드를 짜보면,
49번줄~ 54번줄 까지 constructor(생성자) 함수
49번줄의 Car가 class가 된다.
this 객체는 위의 예제에서는 avante === this
57번줄의 Car : prototype객체로, 저기에 속성이나 메소드를 저장함.
61번줄의 avante가 인스턴스
58번 줄에서 return을 안써도 되는 이유는 생성자함수
prototype, constructor, this 용어 설명
prototype | 모델의 청사진을 만들 때 쓰는 원형 객체 |
constructor | 인스턴스가 초기화될 때 실행하는 생성자 함수 |
this | 함수가 실행될 때, 해당 scope마다 생성되는 고유한 실행컨텍스트 new키워드로 인스턴스를 생성했을 때는, 해당 인스턴스가 this의 값 |
🚨 생성자 함수는 return 값을 만들지 않는다!!!
또 다른 예를 들어보면,
내가 강아지와 고양이에 대해 생각해보면 어떤 '동물(사물)' 이구나!! 라고 생각하면
짖기, 먹기, 달리기 등의 기능을 가지고 있다고 생각할 것이다.
또한, 두개의 '동물(사물)'은 애완동물 이라는 큰 '동물(사물)'안에 포함된다는 것도 생각할 수 있다.
이러한 관점을 프로그래밍에 도입한다 라고 생각하면 된다.
함수들의 집합, 변수들의 목록을 관계성 있는 객체들의 집합으로 분류한다. (이를 추상화라고 한다.)
각각은 메세지를 받을수도있고, 데이터를 처리할 수 있고, 다른 분류에게 메세지 전달도 할 수 있게 한다.
이 분류 하나하나를 객체라고 한다.
객체는 위의 역할을 위해 캡슐화, 정보은닉, 추상화, 상속성 등의 특징을 갖는다.
좋은 설계를 위한 객체지향 프로그래밍의 주요 개념 4가지가 있다.
- 캡슐화
- 상속
- 추상화
- 다형성
-캡슐화 :
데이터(속성)와 기능(메서드)을 따로 정의하는 것이 아닌,
하나의 객체 안에 넣어서 묶는 것이다. 데이터와 기능들이 느슨하게 결합을 한다.
느슨한 결합??
코드 실행 순서에 따라 절차적으로 코드를 작성하는게 아니라,
코드가 상징하는 실제 모습과 닮게 코드를 모아 결합하는 것
예를 들어, 마우스를 구동하기위한 코드를 작성하는데,
스위치 눌리고 -> 전기신호 생기고 -> 전선을 타서 흐르고 -> ... 이렇게 절차를 작성하는게 아니라
마우스의 상태를 프로퍼티로 정하고 클릭, 이동을 메서드로 정해서
코드만 보고도 인스턴스 객체의 기능을 상상할 수 있게 작성하는것.
캡슐화는 "은닉화"의 특징도 포함, 내부 데이터나 내부 구현이
외부로 노출되지 않도록 만드는 것
-추상화 :
내부구현은 아주 복잡한데, 실제로 노출되는 부분은 단순하게 만든다는 개념
예를 들어, 전화기라는 객체가 있으면,
그 안에 스피커, 마이크, 서킷보드 등등이 존재하는 등 내부 구현이 되어있을 것.
그러나 실제로 사용할때는 단순히 수화기를 들고 버튼을 눌러서 해결하는 것처럼
인터페이스를 단순화 한다
캡슐화 | 추상화 |
코드나 데이터의 은닉에 포커스가 맞춰져 있음 | 클래스를 사용하는 사람이 필요하지 않은 메서드 등을 노출시키지않고, 단순한 이름으로 정의하는데에 포커스 |
-상속 :
부모 클래스의 특징을 자식 클래스가 물려받는 것
예를 들어, 사람이라는 클래스가 있으면,
사람은 기본적으로 이름, 성별, 나이 같은 속성,
그리고 먹다, 자다 같은 메서드가 있다
여기에서 학생이라는 클래스를 작성한다고 하면,
앞에서 구현했던 사람 클래스와 똑같은 속성과 메서드를 다시 구현하면
비효율적이다. 학생의 본질은 결국 사람이므로,
상속을 통하여 학생클래스는 사람클래스를 상속받을 수 있다.
-다형성 :
'다양한 형태'를 가질 수 있다는 개념.
"말하다"라는 동작의 본질은 "입으로 소리를 내다"를 의미.
하지만 각기 다른 동물들은 "말할 때" 제각각의 소리를 낸다.
객체 역시 똑같은 메서드라도 다른방식으로 구현될 수 있다.
예를 들어,
Figure 클래스는 하위 클래스에서 모형을 그리는데 사용될 수 있는 Draw 함수를 가지고있다.
그러나 Figure 클래스에는 실제 도형을 그리는 함수 구현 부분을 정의할 수 없다.
이유는 Figure의 하위 클래스인 Triangle, Square, Circle 클래스마다 그리는 방법이 다르기 때문.
이런식으로 똑같은 메서드라도 다른방식으로 구현될 수 있는게 다형성의 개념이다.
객체지향 프로그래밍의 장점
- 코드 재사용이 용이
한번 작성된 코드를 활용해, 동일한 객체를 만들 수 있다. 즉, "모듈화" 시켜서 개발이 가능
- 유지보수 쉽고, 좋은 확장성
절차 지향에서는 코드를 수정할 때 일일이 찾아 수정,
반면, 객체 지향에서는 수정해야 할 부분이 클래스 내부의 변수, 메서드로 있기 때문에
해당 부분만 수정가능, 만들어진 객체를 발전시켜 확장성도 좋음.
객체지향 프로그래밍의 단점
- 개발속도가 느림
생성하고자 하는 객체를 정확히 이해하고, 넓게 생각해야하므로 설계단계부터 오래걸림
- 실행속도가 느림
모든 것을 객체로 생각하기에 추가적인 메모리와 연산에 대한 비용이 들어감