diff --git "a/Chapter_19/JunWon/19-1\355\224\204\353\241\234\355\206\240\355\203\200\354\236\205.md" "b/Chapter_19/JunWon/19-1\355\224\204\353\241\234\355\206\240\355\203\200\354\236\205.md" new file mode 100644 index 0000000..638fe4d --- /dev/null +++ "b/Chapter_19/JunWon/19-1\355\224\204\353\241\234\355\206\240\355\203\200\354\236\205.md" @@ -0,0 +1,137 @@ +# 프로토타입 + +자바스크립트는 명령형, 함수형, 프로토타입 기반, 객체지향 프로그래밍을 지원하는 멀티 패러다임 프로그래밍 언어 + +자바스크립트는 클래스 기반 객체지향 프로그래밍 언어보다 효율적이며 더 강력한 객체지향 프로그래밍 능력을 지니고 있는 프로토타입 기반의 객체지향 프로그래밍 언어 + +자바스크립트는 객체 기반의 프로그래밍 언어이며 **자바스크립트를 이루고 있는 거의 "모든 것"이 객체** + +원시 타입의 값을 제외한 나머지 값들(함수, 배열, 정규 표현식 등)은 모두 객체 + +## 객체지향 프로그래밍 + +객체지향 프로그래밍은 프로그램을 명령어 또는 함수의 목록으로 보는 전통적인 명령형 프로그래밍의 절차지향적 관점에서 벗어나 여러 개의 독립적 단위, 즉 객체(object)의 집합으로 프로그램을 표현하려는 프로그래밍 패러다임 + +객체지향 프로그래밍은 특징이나 성질을 나태내는 **속성attribute/property**을 가지고 있고 이를 통해 실체를 인식하거나 구별할 수 있다 + +다양한 속성 중에서 프로그램에 필요한 속성만 간추려 내어 표현하는 것을 **추상화abstraction**라고 한다 + +"이름"과 "주소"라는 속성을 갖는 person이라는 객체를 자바스크립트로 표현 + +```JavaScript +// 이름과 주소 속성을 갖는 객체 +const person = { + name: 'Lee', + address: 'Seoul' +}; + +console.log(person) // {name: "Lee", address: "Seoul"} +``` + +프로그래머(subject)는 이름과 주소 속성으로 표현된 객체(object)인 person을 다른 객체와 구별하여 인식할 수 있다 + +**속성을 통해 여러 개의 값을 하나의 단위로 구성한 복합적 자료구조**를 개체라고 하며, 객체지향 프로그래밍은 독립적인 객체의 집합으로 프로그램을 표현하려는 프로그래밍 패러다임 + +원이라는 개념을 객체로 만들면 반지름은 원의 **상태를 나타내는 데이터**, 원의 지름, 둘레, 넓이를 구하는 것은 **동작** + +객체지향 프로그래밍은 객체의 **상태state**를 나타내는 데이터와 상태 데이터를 조작할 수 있는 **동작**을 하나의 논리적인 단위로 묶어 생각한다. + +따라서 객체는 **상태 데이터와 동작을 하나의 논리적인 단위로 묶은 복합적인 자료구조**라고 할 수 있다. + +객체의 상태 : 프로퍼티(property) +동작 : 메서드(method) + +## 상속과 프로토타입 + +상속은 객체지향 프로그래밍의 핵심 개념으로, 어떤 객체의 프로퍼티 또는 메서드를 다른 객체가 상속받아 그대로 사용할 수 있는 것을 말한다 + +자바스크립트는 프로토타입을 기반으로 상속을 구현하여 불필요한 중복을 제거한다. + +중복을 제거하는 방법은 기존의 코드를 적극적으로 재사용하는 것이다. 코드 재사용은 개발 비용을 현저히 줄일 수 있는 잠재력이 있어 중요하다. + +## 프로토타입 객체 + +프로토타입 객체란 객체지향 프로그래밍의 근간을 이루는 객체 간 상속을 구현하기 위해 사용된다. + +프로토타입은 어떤 객체의 상위(부모) 객체의 역할을 하는 객체로서 다른 객체에 공유 프로퍼티(메서드 포함)를 제공한다. + +프로토타입을 상속받은 하위(자식) 객체는 상위 객체의 프로퍼티를 자신의 프로퍼티처럼 자유롭게 사용할 수 있다. + +모든 객체는 [[Prototype]]이라는 내부 슬롯을 가지며, 이 내부 슬롯의 값은 프로토타입의 참조다. + +객체가 생성될 때 객체 생성 방식에 따라 프로토타입이 결정되고 [[Prototype]]에 저장된다. + +모든 객체는 하나의 프로토타입을 갖고 모든 프로토타입은 생성자 함수와 연결되어 있다. + +![image](https://velog.velcdn.com/images/nanyong0214/post/c44a81af-ae1d-4e6f-8d44-3916593043d4/image.png) + +[[Prototype]] 내부 슬롯에는 직접 접근할 수 없지만, 위 그림처럼 \_\_proto\_\_ 접근자 프로퍼티를 통해 [[Prototype]] 내부 슬롯이 가리키는 프로토타입에 간접적으로 접근할 수 있다. + +### \_\_proto\_\_ 접근자 프로퍼티 + +**모든 객체는 \_\_proto\_\_ 접근자 프로퍼티를 통해 자신의 프로토타입, 즉 [[Prototype]] 내부 슬롯에 간접적으로 접근할 수 있다.** + +\_\_proto\_\_는 접근자 프로퍼티다. + +\_\_proto\_\_접근자 프로퍼티는 상속을 통해 사용된다. + +\_\_proto\_\_접근자 프로퍼티를 통해 프로토타입에 접근하는 이유 + +\_\_proto\_\_접근자 프로퍼티를 코드 내에서 직접 사용하는 것은 권장하지 않는다. + +### 함수 객체의 prototype 프로퍼티 + +함수 객체만이 소유하는 prototype 프로퍼티는 생성자 함수가 생성할 인스턴스의 프로토타입을 가리킨다. + +### 프로토타입의 constructor 프로퍼티와 생성자 함수 + +모든 프로토타입은 constructor 프로퍼티를 갖는다. 이 constructor 프로퍼티는 prototype 프로퍼티로 자신을 참조하고 있는 생성자 함수를 가리킨다. + +## 리터럴 표기법에 의해 생성된 객체의 생성자 함수와 프로토타입 + +생성자 함수에 의해 생성된 인스턴스는 프로토타입의 constructor 프로퍼티에 의해 생성자 함수와 연결된다. + +이때 constructor 프로퍼티가 가리키는 생성자 함수는 인스턴스를 생성한 생성자 함수 + +```JavaScript +// obj 객체를 생성한 생성자 함수는 Object다. +const obj = new Object(); +console.log(obj.constructor === Object); // true + +// add 함수 객체를 생성한 생성자 함수는 Function이다. +const add = new Function('a', 'b', 'return a + b'); +console.log(add.constructor === Function); // true + +// 생성자 함수 +function Person(name) { + this.name = name; +} + +// me 객체를 생성한 생성자 함수는 Person이다. +const me = new Person('Lee'); +console.log(me.constructor === Person); // true +``` + +리터럴 표기법에 의한 객체 생성 방식과 같이 명시적으로 new 연산자와 함께 생성자 함수를 호출하여 인스턴스를 생성하지 않는 객체 생성 방식도 있다. + +```JavaScript +// 객체 리터럴 +const obj = {}; + +// 함수 리터럴 +const add = function(a, b) { return a + b; }; + +// 배열 리터럴 +const arr = [1, 2, 3]; + +// 정규 표현식 리터럴 +const regexp = /is/ig; +``` + +리터럴 표기법에 의해 생성된 객체도 프로토타입이 존재하지만 프로토타입의 constructor 프로퍼티가 가리키는 생성자 함수가 반드시 객체를 생성한 생성자 함수라고 단정할 수는 없다. + +## 프로토타입의 생성 시점 + +## 객체 생성 방식과 프로토타입의 결정 + +## 프로토타입 체인