
자바스크립트는 프로토타입 기반 언어이다. 이와 관련하여 내용을 정리하려고 한다.
일단 OOP라는 개념을 먼저 보게 되면 객체지향 프로그래밍, 프로그래밍에서 필요한 데이터를 추사화 시켜서 어떠한 상태를 가진 객체를 만들고, 객체들간 상호작용을 통해 로직을 구성하는 프로그램이 방법이다. 기본적으로 추상화, 캡슐화, 상속, 다형성을 지원하면 oop라고 할 수 있다고 생각한다.
Java, c++에서는 class라는 개념이 존재, Javascript는 class라는 개념이 없다. 대신 prototype이 존재한다. 이것 때문에 자바스크립트가 프로토타입 기반 언어이며 객체지향이라고 불린다.
es6부터 Javascript 도 class 문법이 추가되었지만, 문법만 추가되었을 뿐이지 클래스 기반이 아니며, 프로토타입에서 파생되어 나온 문법이다.
가장 중요하게 기억해야 하는 건 자바스크립트의 함수는
객체이다.
자바스크립트에는 Prototype Link 와 Prototype Object라는 것이 존재한다. 그리고 이 둘을 통틀어 Prototype이라고 부른다.
객체는 언제나 함수(Function)로 생성된다.
function Person() {} // => 함수
var personObject = new Person(); // => 함수로 객체를 생성
personObject 객체는 Person이라는 함수로 생성된 객체이다. 일반적인 객체 생성도 예외는 아니다.
var obj = {};
var obj = new Object(); //위와 동일하다
Object를 console에 찍어보면 함수로 나온다.(Object 도 함수!)

Object와 마찬가지로 Function, Array도 모두 함수로 정의되어 있다.
자바스크립트에서 함수가 정의 될 때 2가지 일이 일어난다.
1. 해당 함수에 constructor(생성자) 자격부여
constructor 자격이 부여되면 new 키워드를 통해 객체를 생성할 수 있다. 이것이 함수만 new 키워드를 사용할 수 있는 이유이다.

2. 해당 함수의 Prototype Object 생성 및 연결
함수를 정의하면 함수만 생성되는 것이 아니라 Prototype Object도 같이 생성이 된다. 함수를 정의하면 아래와 같다.

constructor는 Prototype Object와 같이 생성되었던 함수를 가리키고 있다.
__proto__는 Prototype Link이다.
다시 말하면 Prototype Object 는 자신을 원형으로 만들어질 다른 객체가 참조할 prototype 이 되는것이다.
func() 생성자를 통해 객체를 마구마구 찍어내도 func()의 Prototype Object 는 '원형' 하나이며 찍어낸 객체들은 Prototype Object 의 값들을 공유한다.
function Person(){};
Person.prototype.type = "human";
Person.prototype.age = "24";
//PersonPrototypeObject 에 속성추가
let p1 = new Person();
let p2 = new Person();
console.log(p1.type); // human
console.log(p1.age); // 24
console.log(p2.type); // human
console.log(p2.age); // 24
Person.prototype.age = "25";
// 원형의 age 속성 변경
console.log(p1.age); // 25
console.log(p1.age); // 25
console.log(p1.prototype); // undefined
// p1은 객체일뿐이다.
//함수가 아니므로 Prototype Object가 생성되지 않았기 때문에 undefined
생성된 함수는 prototype이라는 속성을 통해 Prototype Object에 접근할 수 있다. Prototype Object는 일반적인 객체와 같으며 기본적인 속성으로 constructor와 __proto__를 가지고 있다.

프로토타입 객체는 constructor 프로퍼티를 갖는다. 이 constructor 프로퍼티는 객체의 입장에서 자신을 생성한 객체를 가리킨다.
test

function test() {}
test.prototype.eyes = 2;
test.prototype.nose = 1;
var kim = new test();
var park = new test():
console.log(kim.eyes); // => 2
kim에는 eyes라는 속성이 없는데도 kim.eyes를 실행하면 2라는 값을 참조하는 것을 볼 수 있다. 위에서 설명했듯이 Prototype Object에 존재하는 eyes 속성을 참조한 것인데 이게 가능한 이유는 kim이 가지고 있는 딱 하나의 속성 __proto__ 가 가능하게 해준다.
prototype 속성은 함수만 가지고 있던 것과는 달리 __proto__속성은 모든 객체가 빠짐없이 가지고 있는 속성이다.
__proto__는 객체가 생성될 때 조상이었던 함수의 Prototype Object를 가리킨다.
kim 객체는 조상인 test로부터 생성 되었으니 test함수의 Prototype Object를 가리킨다.

kim객체가 eyes를 직접 가지고 있지 않기 때문에 eyes 속성을 찾을 때 까지 상위 프로토타입을 탐색한다. 최상위인 Object의 Prototype Object까지 도달했는데도 못찾았을 경우 undefined를 리턴한다다. 이렇게 __proto__ 속성을 통해 상위 프로토타입과 연결되어있는 형태를 프로토타입 체인(Chain)이라고 한다.
(참고로 kim.prototype, park.prototype 불가, 함수로 선언된 것만 prototype 가능.-> test.prototype)
(ex -> function test(){} 는 test.prototype 이 가능하지만 var test={} 는 test.prototype이 불가)
이런 프로토타입 체인 구조 때문에 모든 객체는 Object의 자식이라고 불리고, Object Prototype Object에 있는 모든 속성을 사용할 수 있다.

일급 객체 : 변수나 데이터에 할당 가능, 인자로 넘기기 가능, 리턴값으로 리턴하기 가능
일급 함수 : 함수가 다른 일급 객체와 동일하게 다루어 질때, 일급 함수라고 지칭한다
위와 같은 이유 때문에 자바스크립트는 일급 함수 혹은 일급 객체이다.

JavaScript의 함수가 일급 객체이기 때문에 할 수 있는 것
콜백 패턴 을 사용할 수 있다.고차함수(High-order function) 를 만들 수 있다.클로저(closure) 를 사용해 커링(currying) 과 메모이제이션(memoization) 이 가능하다.https://medium.com/@bluesh55/javascript-prototype-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0-f8e67c286b67
https://frontsom.tistory.com/3