프로토타입 (Prototype)
워밍업
자바스크립트는 프로토타입 기반 언어라고 불린다. 그렇다면 프로토타입이 무엇인지 파헤쳐봐야 재밌어지지 않을까 싶다.
prototype 이라는 단어의 뜻 부터 알고 시작하도록 하자!
prototype
: 원형, 본형, 원작
자바스크립트는 사실 객체지향이다?
Java, C++ 등 다른 언어는 class 라는 개념이 있다. 하지만 자바스크립트에는 존재하지 않는다. ES6 부터 지원된 class 라는 문법이 존재하지만 문법이 추가됐을 뿐 class 기반으로 바뀌지는않았다. class 기반이 아니므로 상속도 존재하지않는다.
자바스크립트가 class 기반이 아닌데도 객체지향이라고 불리는이유는 prototype
이라는것이 존재하기 때문이다. 그렇기 때문에 우리는 prototype
을 공부해야한다.
일급객체 (first-class object)
자바스크립트는 함수를 통해 객체지향을 실현한다. 자바스크립트에서 함수는 일급객체(first-class object) 이다.
일급객체란?
함수를 변수나 다른 데이터구조에 할당 가능
다른 함수의
parameter
로 전달 가능함수의
return
값으로 함수를 반환가능동적으로 프로퍼티를 생성 및 할당 가능,
함수를 통한 객체 생성
자바스크립트 생성자는 자바스크립트에서 객체를 생성되는데 사용되는 함수를 말한다. 하지만 모든 함수가 생성자가 되는 것은 아니다.
Object
는 new
연산자에 의해 생성이 된다. new
연산자를 쓰지않으면 객체가 되지 않는다.
다음 코드를 보자
const str = String"string";console; // stringconst obj = "Object";console; // object
new
연산자를 통해 객체가 생성되는 것을 확인했다. 그렇기 때문에 모든 Object
의 조상은 함수이다.
크롬 콘솔에서 Object
를 입력하면 Object
도 함수인것을 확인할 수 있다.
Prototype
자바스크립트에는 PrototypeObject
PrototypeLink
두개가 존재한다. 이 둘을 Prototype
이라고 부른다.
하나씩 알아보도록하자
PrototypeObject 이해하기
모든 함수 객체는 prototype
이라는 속성을 가지고 있다.prototype
은 원형이라는 뜻이라고했다.
.prototype
은 자기 자신을 생성하게 한 원형 객체를 가리킨다.
{}const obj = ;
위의 코드에서
func.prototype 은 func의 원형객체를 가리킴
이게 뭔소리냐 하면
자바스크립트에서 함수를 정의하면 두가지 일이 일어난다.
1. constructor 자격 부여
함수만이 constructor 자격이 부여되어 new
연산자를 통해 객체를 생성할 수 있게된다
const obj = {};const err = ;//TypeError: obj is not a constructor
2. 해당함수의 PrototypeObject 생성 및 연결
자신이 생성될 당시의 PrototypeObject
객체를 cloning(복제) 하여 만든다.
자신의 분신이 생기는것이다.
다시 말하면 PrototypeObject
는 자신을 원형으로 만들어질 다른 객체가 참조할 prototype
이 되는것이다.
func()
생성자를 통해 객체를 마구마구 찍어내도 func()
의 PrototypeObject
는 '원형' 하나이며 찍어낸 객체들은 PrototypeObject
의 값들을 공유합니다.
예제 코드를 보면 이해가 쉽다
{};Personprototypetype = "human";Personprototypeage = "24";//PersonPrototypeObject 에 속성추가let p1 = ;let p2 = ;console; // humanconsole; // 24console; // humanconsole; // 24Personprototypeage = "25";// 원형의 age 속성 변경console; // 25console; // 25console; // undefined// p1은 객체일뿐이다.//함수가 아니므로 PrototypeObject가 생성되지않았기때문에 undefined
이전의 예제를 웹콘솔로 확인하고 다음 코드를 입력하자
console
뭔가 이상하다. p1
의 속성에는 아무것도 존재하지않는다.
그런데 어떻게 age
와 type
속성에 접근할 수 있는 것일까?
PrototypeLink 이해하기
모든 객체는 __proto__
라는 속성을 가지고있다. 함수도 마찬가지이다.
__proto__
는 숨겨진 링크로써 자신을 만들게 해준 원형인 PrototypeObject
를 가리킨다.
console; // 25console; // humanconsoledirp1;// console.dir 을 해서 내부를 들여다보면// p1에는 age, name 속성이 존재하지않는다
p1
에 age
와 type
속성이 존재하지않는다는것을 확인했다.
하지만 __proto__
속성이 존재한다.
이부분이 포인트다
__proto__
내부를 확인해보니 age
, type
속성이 존재했다.
즉, p1
의 속성으로서 존재하지는 않지만 __proto__
를 통해 p1
을 만들게 해준 PersonPrototypeObject
내의 age
와 name
에 접근한것이다.
이렇게 __proto__
를 통해 상위 prototype
과 연결된 형태를 프로토타입 체인(Prototype Chain) 이라 한다.
프로토타입 체인을통해 최상위객체인 Object
의 메서드들도 사용할 수 있는 것이다.
console;
다시 들여다보기
우리는 앞서 상위 prototype
에 참조된다고했다. 그렇다면 두가지 의문이 생긴다.
만약 프로토타입체인을 통해서 못찾으면?
console; //undefinedhahaha
가 상위 프로토타입에 존재할때까지 프로토타입체인을 통해 거슬러 올라간다. 하지만 그래도 없다면undefined
반환상위
PrototypeObject
내의 속성이름과 객체자체속성의 이름이 겹친다면?
다음과 같은 예가 있다
{};fooprototypea = 1;fooprototype{ console; };const obj = ;console; // 1console;// Hello 1// undefinedconsole; // foo {}obja = 5;obj{ console; };console; // 5console;// Bye 5// undefined;console; // foo { a: 5, greet: [Function] }
obj.a = 5
obj.greet
구문은 상위PrototypeObject
의 속성을 재정의 한것인가?
정답은 No
크롬의 콘솔창에서 마지막 구문의 내부를 살펴보면
foo {a: 5, greet: ƒ}a: 5greet: ƒ ()__proto__:a: 1greet: ƒ ()constructor: ƒ foo()__proto__: Object
자신의 객체의 속성을 추가한것임을 알 수 있다.
그럼 어떻게 상위 PrototypeObject
의 속성을 변경하는가?
PrototypeObject.prototype
속성을 이용해서 수정하거나
객체의 Object.__proto__
을 이용해서 수정하거나 하면된다.
// 방법 1fooprototypea = 5;fooprototype{ console; };// 방법 2obj__proto__a = 5;obj__proto__{ console; };
하지만 전자의 방법을 추천한다. 어떤 원형을 바꿨는지 명확하게 알 수 있기 때문이다.
참고문서
https://medium.com/@bluesh55/javascript-prototype-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0-f8e67c286b67
http://rhio.tistory.com/236
http://insanehong.kr/post/javascript-prototype/
http://www.nextree.co.kr/p7323/
아무말 대잔치
프로토타입이 제일 중요하다고 들어서 빡집중했다
프로토타입 상속이 더 어려울것같다. 무섭다.
잠을 4시간잤더니 너무 피곤하다.
인터넷의 문서들은 정말 양질의 자료들이 많은것같다.
프로토타입이 강력한만큼 그만큼 책임이 따를것같다
'복습 > Javascript' 카테고리의 다른 글
[Javascript] 객체지향 자바스크립트 [클래스] (0) | 2018.02.22 |
---|---|
[Javascript] 객체지향 자바스크립트 [상속] (0) | 2018.02.19 |
[Javascript] 객체지향 자바스크립트 [컬렉션] (0) | 2018.02.14 |
[Javascript] 객체지향 자바스크립트 [이터레이터, 이터러블, 제너레이터] (0) | 2018.02.13 |
[Javascript] 객체지향 자바스크립트 [소괄호의 의미와 IIFE] (0) | 2018.02.13 |