객체 지향 프로그래밍이란 프로그래밍 방법론 중에 하나로써 프로그램 설계를 객체 위주 즉 프로그램의 모든 부분을 객체로 세분화 해서 설계가 되는 것이 특징이다
절차 지향 언어
객체 지향 언어
객체 지향 프로그래밍은 일반적으로 클래스라는 것이 있다 이는 새로운 객체(인스턴스)를 찍어내는 설계도라고 생각하면 편하다 이 설계도를 가지고 찍어낸 인스턴스들은 클래스의 속성과 메소드를 가지고 있는 특징이 있다
클래스에서 속성은 그 클래스의 정보를 나타낸다 예를 들어 자동차의 정보로 속도,색깔,브랜드 등이 있을 수 있다
메소드는 그 클래스의 동작을 나타낸다 같은 예시로 자동차가 출발한다, 멈춘다, 속도를 올린다 등이 있을 수 있다
클래스의 속성과 메소드를 다시 정의하지 않고 새로운 인스턴스를 만들어 낼 때 다시 사용할 수 있다는 특징이다 개발자는 클래스의 모든 정보를 캡슐 처럼 인스턴스에 전달 할 수 있기 때문에 이런 속성을 가진다
클래스의 정보를 다른 클래스의 전달할 수 있다 이를 상속성이라 표현한다 클래스의 정보를 전달 받은 클래스를 형식적으로 자식 클래스 전달 해준 클래스를 부모 클래스 라고 한다 자식 클래스는 부모의 속성과 메소드를 다시 정의하지 않고 사용이 가능하다
추상화 특징은 클래스를 사용하는 개발자가 클래스 내부 메소드의 구현이 어떻게 되었는지 알지 못해도 인스턴스를 만들어서 사용할 수 있게 해주는 특징이다
예를 들어 전화기 클래스의 call 메소드가 있다고 가정하면 이 클래스를 사용하는 개발자는 새로운 전화기 인스턴스를 만들어서 call 메소드를 호출하면 되는 것이다 이 과정에서 call 메소드의 내부적인 구현을 몰라도 사용이 가능하다
다형성 특징은 상속성과 비슷하지만 다른게 작동한다 다형성을 통해 구현된 자식 클래스는 부모클래스의 메소드를 그대로 받아 들이지 않고 자신의 정보를 이용하여 메소드를 수정할 수 있는 방식이다
위 그림의 예로 들어 일반적인 동물 클래스를 부모클래스라 하고 부모클래스 내부의 speak라는 메소드가 구현이 되어있다 이를 각기 다른 동물에게 상속해주면서 여러 동물들은 자신의 속성을 이용해 speak 메소드를 실행한다
자바스크립트에서 클래스를 사용하는 방법은 두가지가 있다 하나는 es5까지 사용한 함수 선언과 비슷한 방식과 다른 하나는 es6에서 새롭게 추가된 class 키워드를 이용하는 방식이다
//ES5
function PersoneEs5(name,age){
this.name=name;
this.age=age;
PersoneEs5.prototype.meal=function(){
console.log('식사를 합니다');
}
PersoneEs5.prototype.sleep=function(){
console.log(name+'이 잠을 잡니다');
}
}
//ES6
class PersoneEs6{
constructor(name,age){
this.name=name;
this.age=age;
}
meal=function(){
console.log('식사를 합니다');
}
sleep=function(){
console.log(this.name+'이 잠을 잡니다');
}
}
위와 같이 클래스를 사용하기 전에 사용하던 4가지 방식이 있다
var Car=function(position){
var someInstance = {};
someInstance.position=position;
someInstance.move=function(){
this.position+=1;
}
return someInstance;
}
var car1=Car(5);
이와 같이 함수 내부에 객체를 생성해서 리턴하는 방식이다 그래서 함수 호출만 해주면 인스턴스가 생성이 된다
var extend = function(to, from){
for ( var key in from) {
to[key] = from[key];
}
};
var someMethods= {};
someMethods.move = function(){
this.position+=1;
};
var Car=function(position){
var someInstance = {
position: position;
};
extend(someInstance, someMethod);
return someInstance;
}
var car1=Car(5);
이 방식은 함수 밖에서 메소드를 정의해서 인스턴스를 반환하기 전에 합쳐주는 방식이다. 이 방식을 사용하는 이유는 Functional 방식은 모든 인스턴스에게 메소드를 할당하기 때문에 메모리를 많이 먹는다
그러나 위와 같이 하면 someMethods라는 주소만 사용하기 때문에 메모리 효율이 좋아진다.
var someMethods= {};
someMethods.move = function(){
this.position+=1;
};
var Car=function(position){
var someInstance = Object.create(someMethods);
someInstance.position = position;
return someInstance;
}
var car1=Car(5);
2번쨰 방식보다 훨씬 간단한 방식이다 object.create는 특정 객체를 프로토타입으로 하는 객체를 생성해준다
var Car = function(position) {
this.position = position;
};
Car.prototype.move = function() {
this.position +=1;
};
var car1 = new Car(5);
이 방식은 직접 프로토타입을 이용하여 작성하는 방식이다 제일 간다하고 많이 쓰인다 위에 코드에서 보면 인스턴스를 생성할 때 new 연산자를 이요하는 것을 알 수 있다
위 클래스 생성 패턴에서 프로토타입이라는 단어를 많이 썼는데 정확히 이게 무엇인지 알아보겠다 자바스크립트는 프로토타입 기반 언어라고 하는 이유는 다른 언어에서 있는 class라는 개념이 자바스크립트에서는 prototype으로 구현 되었기 때문이다 자바스크립트의 모든 함수는 prototype이라는 속성을 가지고 있다
function Student() {
this.legs = 2;
this.arms = 2;
}
let lee = new Student();
위와 같이 선언하면 인스턴스를 만들 수 있지만 몇백개의 학생을 생성해야하면 legs,arms가 각각의 인스턴스마다 생성되어 메모리를 많이 사용하게 된다 이를 아래와 같이 해결 할 수 있다
function Student() {}
Student.prototype.legs = 2;
Student.prototype.arms = 1;
let lee = new Student();
console.log(lee.arms); // => 2
이렇게 선언이 되면 어딘가에 존재하는 Student.prototype에서 legs,arms를 가져다 쓸 수 있다 이런 원리를 아래에서 다루겠다
함수를 정의하면 함수의 생성과 함께 Prototype Object도 같이 생성이 된다 prototype object는 두가지 속성을 가지고 있다
javascript의 모든 객체는 proto 라는 속성을 가지고 있다 이 속성은 객체가 생성될 때 이 객체를 생성한 함수의 prototype object를 가리킨다
처음 예시를 든 코드에서 lee 객체는 arms, legs 속성을 가지고 있지 않기 때문에 이 속성을 찾기 위해 위와 같은 체이닝을 이용해 탐색을 한다
lee 에서 탐색을 실행해서 → Student prototype object → Object prototype object(최상위 객체의 prototype object) 까지 찾아본다 만약 존재하지 않으면 undefined를 리턴한다