🥙 프로토타입 체인이란
OOP의 개념중 하나인 상속을 구현하려면 프로토타입 체인을 사용합니다. 자바스크립트에서 객체의 속성이나 매서드를 찾을 때, 해당 객체의 프로토타입을 따라 올라가면서 마치 유전자를 탐색하듯 검색을 합니다. 만약 해당 객체에서 찾는 속성이나 메서드가 없다면 그 객체의 프로토타입을 따라 올라가며 검색하고 더이상 프로토타입이 없을 때까지 계속해서 검색합니다. 이과정에서 프로토타입 체인에 있는 모든 객체의 속성과 메서드를 사용할 수 있습니다.
객체를 생성하는 Tv템플릿에 tv1이라는 인스턴스를 생성해서 데이터가 들어간 객체를 만들 수 있습니다.
부모는 자식에게 name과 price라는 속성을 상속해줍니다.
자바스크립트에는 prototype는 사람의 유전자와 비슷한역할을 합니다.
부모의 유전자를 조작하고,
자식에게서 그 속성을 찾으면 프로토타입체인을 따라 부모의 속성을 찾아 보여줍니다.
부모객체(Tv)의 prototype(유전자)에 size 속성을 추가하고,
자식객체(tv1)에게 없는 size속성을 찾으면
자바스크립트는 프로토타입 체인을타고 올라가 해당 속성을 찾아내 출력합니다.
자식객체에 먼저 묻고 없으면 부모의 유전자를 뒤지고 없으면 또 부모의 부모의 부모 유전자에게 묻습니다.
이것이 바로 프로토타입 체인입니다.
🥙.prototype
자바스크립트에서의 객체는 모두 .prototype 프로퍼티를 가집니다. 이 프로퍼티는 해당 객체의 부모역할을 하는 다른 객체를 가르키는데 이 객체를 프로토타입객체라고 합니다.
프로토타입 객체는 자식 객체에서 상속할 수 있는 메소드과 프로퍼티를 가지고 있습니다. 따라서 객체에서 어떤 메소드나 프로퍼티를 호풀할 때, 해당 객체에 해당 메소드나 프로퍼티가 없으면 자바스크립트는 자동으로 객체의 프로토타입 객체에서 찾습니다.
예를들어 Array타입의 프로토타입 객체(Array.prototype)에는 push(),pop() 등의 메소드가 정의되어 있습니다. 따라서 배열 객체에서 push()메소드를 호출할 때, 해당 메소드가 배열 객체에 직접 정의되어있지 않더라도, 자바스크립트는 배열 객체의 프로토타입 객체에서 해당 메소드를 찾아서 호출합니다.
Q. array 자료에 .push()나 .length를 붙일 수 있는 이유?
저희는 배열을 두가지 방법으로 만들 수 있습니다.
1. [대괄호]안에 element들을 넣어주거나 ex) [1,2,3]
2. Array 클래스를 이용해 만들어 줍니다 ex) new Array(1,2,3)
그래서 배열의 push 메소드나, length 값은 어떻게 얻는 걸까요?
바로 Array라는 부모객체의 유전자 즉, 프로토타입객체를 찾아 메소드나 속성을 찾습니다.
.prototype 을 이용해 배열의 프로토타입 객체를 살펴보겠습니다.
우리가 알고있는 배열의 메소드와 속성들이 모두 Array라는 부모객체에 저장되어있습니다.
변수로 정의한 배열에 원래 없는 메소드와 속성들은 프로토타입 체인을 따라 프로토타입 객체를 찾아서 호출합니다.
.prototype을 이용해서 모든 array자료에서 사용할 수 있는 새로운 함수를 만들 수 도 있습니다.
어떤 함수인지 선언을 안해주어 undefined가 떴을뿐 모든 array에 적용될 수 있는 함수를 만들었습니다.
함수이름이 다르다면 함수가 아니라는 경고문이 뜨게 됩니다.
이처럼 .prototype을 이용하면 객체의 부모유전자를 확인하고 조작이 가능합니다.
🥙.__proto__
모든객체는 __proto__ 접근자 프로퍼티를 통해 자신의 프로토타입 내부 슬롯에 간접적으로 접근 할 수 있습니다. 내부슬롯은 프로퍼티가 아니여서 원칙적으로 일부 내부 슬롯과 내부 메서드에 한하여 간접적으로 접근할 수 있는 수단을 제공하기는 합니다. 접근자 프로퍼티를 통해 간접적으로 내부슬롯의 값, 즉 프로토타입에 접근할 수 있습니다.
Object.prototpe의 접근자 프로퍼티인 __proto__는 getter/setter 함수라고 부르는 접근자 함수를 통해 내부슬롯의 값, 즉 프로토타입을 취득하거나 할당합니다.
여기서 superObj와 subObj는 일면식도 없는 남남입니다.
하지만 자바스크립트는 클래스가 아닌 객체(인스턴스)를 직접 다른객체의 자식으로 만들어 줄 수 있습니다.
1. __proto__ 라는 속성(프로퍼티)링크를 통해서 subObj가 superObj의 자식으로 만들어줍니다.
2. subObj.superVal을 호출했을때, 자바스크립트는 먼저 let subObj에서 superVal를 찾지만
3. 없어요..그냥없어요...
4. __proto__속성이 담고 있는 객체에서 superVal를 찾아서 출력을 해줍니다!
subObj.superVal = "sub"; //객체를 바꾸는거지 객체의 proto를 바꾸는게 아니다
console.log("super.superVal =>", superObj.superVal);
만약 자식 객체에서 없던 부모요소의 속성을 바꿔주면 __proto__로 연결되어있기 때문에 부모요소의 속성을 바꿔줄 순 없습니다.
🔗코딩애플 프로토타입
https://youtu.be/wUgmzvExL_E
🔗생활코딩 __proto__
https://youtu.be/gthQmqW_Dk4
'JavaScript' 카테고리의 다른 글
React SPA React Router (4) | 2023.03.23 |
---|---|
Asynchronous (0) | 2023.03.19 |
프로토타입과 클래스 (0) | 2023.03.15 |
객체 지향 프로그래밍 (2) | 2023.03.15 |
클래스와 인스턴스 (4) | 2023.03.15 |