컴퓨터 프로그래밍의 패러다임 중 하나로, 명령어의 목록으로 보는 시각이 아닌, 객체들의 모임으로 파악하는 프로그래밍이다.

ex) Java, C++, C#, Python, PHP, JavaScript, Ruby, Perl, Object Pascal, Objective-C, Dart, Swift, Scala, Common Lisp 등
프로그램 안에서 각각의 명령어에 의해 정의되어진다. 그러므로 그 순서와 절차를 어떻게 정해주는지가 중요하다.
ex) C, COBOL, Fortran, LISP, Perl, HTML, VBScript 등

순서와 절차를 중시하기 때문에 모든 기승과 속성의 관계성이 떨어지고, 한 기능을 수정한다면 모든 것을 전부 수정해야한다.
그래서 객체 지향 프로그래밍이 이 문제를 해결해 준다.
모든 것이 객체(Object)로 이루어져 있다.
서로 관계가 있는 속성과 기능들을 묶어놓은 blueprint를 정의한다.
그 정의한 blueprint를 객체로 만들어 사용한다.
class : 속성과 기능을 묶어놓은 blueprint
object : 이러한 blueprint의 속성과 기능을 정의한다.

절차 지향적 언어와는 다르게 서로 독립적이라서 하나의 속성이나 기능을 수정해야 한다고 해도 다른 객체들을 건드리지 않고 그 부분만 손쉽게 수정할 수 있다.
객체들을 재사용할 수 있고 변형해서 사용할 수도 있다.
attribute / properties : 속성
methods : 기능 혹은 함수


property와method를 하나로 묶어 object로 정의하는것
ex)

절차 지향적 언어에서는 각각 한명에 대한 급여 계산에 필요한 정보를 각각 입력해서 급여를 구해야 되지만,
객체 지향적 프로그래밍에서는 속성과 함수를 employee라는 객체에 함께 묶어둔 예시로 여러 employee가 생겨도 employee1, employee2... 등으로 변형해서 사용할 수 있다.
장점 : 코드의 간결화와 재사용의 용이함
부모 클래스가 가진 속성과 기능을 자식 클래스가 물려받는 것
장점 : 복잡도를 줄여주고 불필요한 코드 제거
어떠한 공통의 속성이나 기능을 하나로 묶어 클래스로 정의하는 것

ex) 고양이, 강아지, 물고기 등 -> 동물 또는 생물이라는 객체로 묶어서 정의할 수 있다.
장점 : 인터페이스를 간단하게 만들어주고 변화의 영향이 감소
부모 클래스에서 물려받은 속성과 기능을 자식 클래스가 상황에 맞게 재정의해서 사용할 수 있는 것

ex) HTML 태그에서 TextBox, Select, CheckBox가 모두 각각 render()라는 기능이 필요하다고 할때 TextBox에서 render(), Select에서 render(), CheckBox에서 render()를 정해주는게 아니라 HTMLElement에서 render()를 정해준 다음에 각각 부모를 상속받고 render()를 쓰게 한다.
만약 다형성이 없다면?!

위의 그림처럼 각각 정해줘야되서 복잡해질 것이다;;;
장점 : 코드의 깔끔화
JavaScript에 Class가 나오기 전에는 Class를 함수를 이용해서 사용했다.
class 함수를 이용해 클래스를 만들고 instance를 만드는 작업은 총 4가지가 있었는데, 이를 Instantiation Patterns라고 한다.
함수를 이용해서 찍어내는 방식
ex)
var Car = function() {
var someInstance = {};
someInstance.position = 0;
someInstance.move = function() {
this.position += 1;
}
return someInstance;
}
// 먼저 Car라는 함수를 만든다.
// 그리고 함수를 실행했을 때 찍어내줄 객체를 선언하고 맨 마지막에 리턴시킨다.
// someInstance의 position을 0으로 초기화해준다.
(Car 함수가 실행되어 나온 인스턴스의 position의 초기값은 항상 0이 된다.)
// someInstance에 move라는 메소드를 추가해준다.
(function 내부에 있는 this는 someInstance를 뜻하기 때문에
this.position === someInstance.position이고,
실행시 position 값이 1만큼 증가한다.)
이렇게 정의한 후
var car1 = Car();
var car2 = Car();
car1.move();
console.log(car1) // position:1
ex)
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,
};
return someInstance;
};
var car1 = Car(5);
var car2 = Car(0);
car1.move();
console.log(car1) // position:6
// 먼저 Car 함수를 선언해주고 바로 position을 someInstance의 property로 넣어준다.
// 그리고 메소드를 담아줄 객체를 생성한다.
// 그리고 someInstance와 someMethods를 합치는 extend 함수를 만들어서 Car 함수 내부에서 합쳐준다.
이전의 Functional 방식은 인스턴스를 생성할 때마다 모든 메소드를 someInstance에게 할당하므로, 각각의 인스턴스들이 메소드의 수 만큼의 메모리를 더 차지하기 때문이다.
하지만 Functional Shared 방식을 사용하면 someMethods라는 객체에 있는 메소드들의 메모리 주소만을 참조하기 때문에 메모리 효율이 좋아진다.

ex)
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);
var car2 = Car(10);
// functional shared와 비슷하게 작성해주되 var someInstance = Object.create(someMethods); , someInstance.position = position; 이 부분으로 수정해준다.
// 함수를 만들어 합쳐주는 대신 Object.create을 사용하는게 차이점이다.
특정 객체를 프로토타입으로 하는 새로운 객체를 생성하는 함수
직접 프로토타입을 이용하여 만드는 방법으로, 제일 많이 쓰인다.
ex)
var Car = function(position) {
this.position = position;
};
Car.prototype.move = function() {
this.position += 1;
};
var car1 = new Car(5);
var car2 = new Car(10);
// 먼저 Car 함수를 만들고 position을 정의해준다.
// 메소드를 프로토타입으로 만들어준다.
// 인스턴스를 찍어낼 때는 new operator를 붙여준다.
사용자 정의 객체 타입 혹은 내장 객체 타입의 인스턴스를 생성하는 것
자신의 부모 역할을 담당하는 객체와 연결되어 있고 마치 객체 지향의 상속 개념과 같이 부모 객체의 프로퍼티 또는 메소드를 상속받아 사용할 수 있게 하는 부모 객체