# OOP (Object Oriented Programming)

npm 모듈 같은거 쓰기 편한, 발명품 객체를 위주로 코드를 정리한다.

물건을 발명한다고 생각한다.

레고를 준다. 이걸 이용해서 무엇을 만들지는 창의성에 달린것이다.

**너무 깜깜해! 램프를 만들고 싶어!**

```javascript
var lamp = {
  brightness: 0, //this를 붙이지 않아도 접근 가능하다. 함수형태가 아니라서 'ㅁ'?
  turnOn: function () {
    this.brightness = 100;
  },
  turnOff: function () {
    this.brightness = 0;
  }
};

lamp.turnOn();
lamp.turnOff();
lamp.brightness = 10000000000000;
```

```javascript
function lamp() {
  var brightness = 0; // 캡슐화 지역변수로 만들었다.
  this.turnOn = function () { // 클로저로 기억한다.
    brightness = 100;
    console.log(brightness);
  };
  this.turnOff = function () {
    brightness = 0;
  }
};

var myLamp = new lamp();
myLamp.turnOn();
```

## 캡슐화(Encapsulation)

사용자가 내부정보를 접근하지 못하도록 한다.

```javascript
var lamp = (function(){
  var brightness = 0;

  return { // 클로저로 기억하고 있다. 객체로 리턴해준다. - 포인트
    turnOn: function () {
      brightness = 100;
    },
    turnOff: function () {
      brightness = 0;
    }
  }
})(); // 지역변수로 만듬

lamp.turnOn();
lamp.turnOff();
```

## 추상화(Abstraction)

소프트는 복잡할 수 있으나, 사용자는 기계안에 상세내용을 알 필요는 없다. 사용자는 간단하게 사용해야 한다.

factory 함수 - 함수를 만드는데 객체를 return하게 만든다. 생성자함수와 클래스가 아니다.

공장처럼 찍어내는 함수를 말한다.

[link](https://medium.com/javascript-scene/javascript-factory-functions-vs-constructor-functions-vs-classes-2f22ceddf33e)

현관문에 있는 램프를 만들고자 한다. 이 램프는 사용자가 간단하게 사용하면 되는거지, 이 상세내용을 알 필요는 없다.

```javascript
var lamp = (function () {
  var brightness = 0;
  return {
    turnOn: function() {
      brightness = 100;
    },
    turnOff: function() {

    },
    autoOnAndOff: function() {
      brightness = 100;
      setTimeout(function () {
        brightness = 0;
      }, 5000)
    }
  };
})();

lamp.autoOnAndOff();
```

램프가 몇 개 더 필요합니다.

**construrctor 함수를 사용하여 재사용성을 높였다**

```javascript
function Lamp () {
  this.brightness = 0; // 여기서 brightness가 노출이 되지만 재사용성을 더 중요시하여 노출시킴 
}
Lamp.prototype.turnOn = function () {
  this.brightness = 100;
};
Lamp.prototype.tyrnOff = function () {
  this.brightness = 0;
};
Lamp.prototype.autoOnAndOff = function () {
  var that = this;
  that.brightness = 100;
  setTimeout(function () {
    that.brightness = 0;
  }, 5000);
};

var lamp1 = new Lamp();
var lamp2 = new Lamp();
var lamp3 = new Lamp();
```

**Factory를 사용하여 brightness를 이용해서 brightness를 private하게 만듬**

```javascript
var lampPrototype = {
  brightness: 0,
  turnOn: function() {
    this.brightness = 100;
  },
  turnOff: function() {
    this.brightness = 0;
  },
  autoOnAndOff: function () {
    this.brightness = 100;

    setTimeout(() => {
      this.brightness = 0;
    }, 5000);
  }
};

function createLamp () {
  return Object.create(lampPrototype); // 객체를 리턴한다. 팩토리 함수다.
}

var lamp1 = createLamp();
var lamp2 = createLamp();
var lamp3 = createLamp();
```

Factory 함수란? 어떠한 함수를 만드는데 객체를 리턴하게 만든다. 그치만 이것은 생성자함수나 클래스가 아니다.

**만약 brightness를 보호하고 싶다면?**

```javascript
function createLamp () {
  var brightness = 0; // 클로저를 이용하고, 지역변수로 만든다.
  return { // 객체를 리턴한다. 팩토리함수
    turnOn: function() {
        brightness = 100;
    },
    turnOff: functi on() {
      brightness = 0;
    },
    autoOnAndOff: function () {
      brightness = 100;

      setTimeout(() => {
        brightness = 0;
      }, 5000);
    }
  };
}

var lamp1 = createLamp();
var lamp2 = createLamp();
var lamp3 = createLamp();
```

## Inheritance

**SOLID Principle**, Principle, KISS, GRASP

```javascript
function Car (owner) {
  this.owner = owner;
}

Car.prototype.soldTo = function (newOwner) {
  this.owner = newOwner;
};

var car = new Car('ken nim');
var car2 = new Car('hoho');
```

**전기차를 만들어보자**

```javascript
function ElectricCar (owner) {
  this.owner = owner;
  this.power = 0;
}

ElectricCar.prototype.soldTo = function (newOwner) {
  this.owner = newOwner;
}

ElectricCar.prototype.recharge = function (time) {
  var that = this;
  setTimeout(function () {
    that.power = Math.min((time / 100), 100);
  }, time);
};
```

Car생성자 함수와 유사한 부분이 있다.

* 주인이 존재한다.
* 양도를 한다.

자동차가 큰 카테고리에 있고 그 밑에 전기차가 있다. 행동 위임을 통해 자동차의 기능을 전기차가 사용하도록 하자.

```javascript
function ElectricCar (owner) {
  // 여기에 this는 new ElectricCar('ken'); 하면서 생성된 빈 객체의 this이다.
  // Car에 빈객체의 this를 설정하였다.
  Car.call( , owner);
  this.power = 0;
}

ElectricCar.prototype = Object.create(Car.prototype);
// console.log(ElectricCar.prototype.constructor) //car가 나온다. 
// ElectricCar.prototype = { constructor: ElectricCar };
// ElectricCar.prototype로 접근할 수 있는 프로토타입이라는 객체는 항상 constructor라는 속성을
// 가진다. 하지만 위에서 새로운 Object.create(Car.prototype);를 만들어줘서
// constructor를 잃는것이다.
ElectricCar.prototype.constructor = ElectricCar;

ElectricCar.prototype.recharge = function (time) {
  var that = this; // ec라는 reference를 생성해줬다.
  setTimeout(function () { // 함수가 끝난 후 비동기로 실행되기 때문에 this를 잃고 만다.
    that.power = Math.min((time / 100), 100); // 스코프체인을 타고 올라가서 that을 찾는다.
  }, time);
};

var ec = new ElectricCar('ken');
ec.soldto('aaa') // soldto라는게 실제 만들어놓진 않았지만 프로토타입 체인으로 사용이 가능해졌다.
```

## SOLID Principle(객체지향 설계)

객체지향 설계를 말하며, 객체지향의 다섯가지 기본 원칙을 말한다. 시간이 지나도 유지보수와 확장이 쉬운 시스템을 만들고자 할 때 이 원칙들을 함께 적용할 수 있다.

| 개념                                         | 설명                                   |
| ------------------------------------------ | ------------------------------------ |
| Single responsibility principle(단일 책임 원칙)  | 한 클래스는 하나의 책임만 가져야 한다.               |
| Open /  closed principle(개방 폐쇄 원칙)         | 확장에는 열려 있어야 하고 변경에는 닫혀 있어야한다.        |
| Dependency inversion principle(의존관계 역전 원칙) | 프로그래머는 추상화에 의존해야지, 구체화에 의존하면 안된다.??? |
|                                            |                                      |


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://seula00027.gitbook.io/til/vanillacoding/03.oop.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
