[JS/node] prototype
prototype
원형 객체
필기
- 프로토타입은 객체 지향 구현을 위해 사용할 수 있다.
- 해당 클래스의 메소드 정보가 담겨 있다.
Achievement Goals
- Javascript 객체 프로토타입을 이해하고,
- 프로토타입 체인이 어떻게 동작하는지,
- 또 프로토타입 속성에 새 메소드를 추가하는 방법을 배웁니다.
prototype 기반 언어, JavaScript
모든 객체들이 메소드와 속성들을 상속 받기 위한 템플릿으로써 프로토타입 객체(prototype object)를 가진다
prototype chain
상속
을 JavaScript에서 구현할 때 사용
프로토타입 객체도 또 다시 상위 프로토타입 객체로부터 메소드와 속성을 상속 받을 수도 있고 그 상위 프로토타입 객체도 마찬가지.
다른 객체에 정의된 메소드와 속성을 특정 객체에서 사용할 수 있도록 하는 근간
상속되는 속성과 메소드들은 (각 객체가 아니라) 객체의 생성자의 prototype이라는 속성에 정의되어 있습니다.
__proto__
[dunder proto]
특정 객체의 프로토타입 객체에 접근 가능하게 하는 속성
(프로토타입 체이닝에 의해서 __proto__
를 참조하게 하는 자바스크립트 자체의 작동 원리)
prototype 객체(개별 객체의 속성)
모든 객체들이 가지는 메소드와 속성들을 상속 받기 위한 템플릿
__proto__
속성으로 접근 가능한 내장 객체
prototype 속성(생성자의 속성)
상속 받은 멤버들(속성, 메소드들)이 정의된 객체의 생성자에 있는 속성
프로토타입 체인을 통해 상속하고자 하는 속성과 메소드를 담아두는 버킷으로 주로 사용되는 객체
예시
Object.
(x)
Object.prototype.
(o)
개별 객체의 속성
생성자 속성
원본 생성자 함수 자신
프로토타입 체인 동작 증거
person1의 프로토타입 객체인 Person()에 정의된 멤버들
— name, age, gender, interests, bio, greeting을 볼 수 있습니다.
또한 — watch, valueOf처럼 Person()의 프로토타입 객체인 Object에 정의된 다른 멤버들도 보실 수 있습니다. 이는 프로토타입 체인이 동작한다는 증거입니다.
person1.valueOf()
- 브라우저는 우선 person1 객체가 valueOf() 메소드를 가지고 있는지 체크합니다.
- 없으므로 person1의 프로토타입 객체(Person() 생성자의 프로토타입)에 valueOf() 메소드가 있는지 체크합니다.
- 여전히 없으므로 Person() 생성자의 프로토타입 객체의 프로토타입 객체(Object() 생성자의 프로토타입)가 valueOf() 메소드를 가지고 있는지 체크합니다.
- 여기에 있으니 호출하며 끝납니다!
Human이라는 클래스와 인스턴스, 그리고 프로토타입의 관계
[그림] 클래스 Human과 인스턴스, 그리고 프로토타입의 관계 모식도
Array(배열) 클래스와 인스턴스, 그리고 프로토타입의 관계
[그림] 배열 arr과 Array, 프로토타입의 관계 모식도
extends 키워드
클래스를 다른 클래스의 자식으로 만들기 위해 class 선언 또는 class 식에 사용
super 연산자
상위 클래스의 생성자를 호출하며 super()의 매개변수를 통해 상위 클래스의 멤버를 상속받을 수 있는 코드
필독 레퍼런스
Reference Code
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Object-oriented JavaScript class further exercises</title>
</head>
<body>
<p>This example requires you to enter commands in your browser's JavaScript console (see <a href="https://developer.mozilla.org/en-US/docs/Learn/Common_questions/What_are_browser_developer_tools">What are browser developer tools</a> for more information).</p>
</body>
<script>
function Person(first, last, age, gender, interests) {
this.name = {
'first': first,
'last' : last
};
this.age = age;
this.gender = gender;
this.interests = interests;
this.bio = function() {
// First define a string, and make it equal to the part of
// the bio that we know will always be the same.
var string = this.name.first + ' ' + this.name.last + ' is ' + this.age + ' years old. ';
// define a variable that will contain the pronoun part of
// the second sentence
var pronoun;
// check what the value of gender is, and set pronoun
// to an appropriate value in each case
if(this.gender === 'male' || this.gender === 'Male' || this.gender === 'm' || this.gender === 'M') {
pronoun = 'He likes ';
} else if(this.gender === 'female' || this.gender === 'Female' || this.gender === 'f' || this.gender === 'F') {
pronoun = 'She likes ';
} else {
pronoun = 'They like ';
}
// add the pronoun string on to the end of the main string
string += pronoun;
// use another conditional to structure the last part of the
// second sentence depending on whether the number of interests
// is 1, 2, or 3
if(this.interests.length === 1) {
string += this.interests[0] + '.';
} else if(this.interests.length === 2) {
string += this.interests[0] + ' and ' + this.interests[1] + '.';
} else {
// if there are more than 2 interests, we loop through them
// all, adding each one to the main string followed by a comma,
// except for the last one, which needs an and & a full stop
for(var i = 0; i < this.interests.length; i++) {
if(i === this.interests.length - 1) {
string += 'and ' + this.interests[i] + '.';
} else {
string += this.interests[i] + ', ';
}
}
}
// finally, with the string built, we alert() it
alert(string);
};
this.greeting = function() {
alert('Hi! I\'m ' + this.name.first + '.');
};
};
let person1 = new Person('Tammi', 'Smith', 32, 'neutral', ['music', 'skiing', 'kickboxing']);
</script>
</html>
객체지향 왜 해야 해?
기계적 사고방식이 너무 어려웠기 때문에
사람이 사고하는 방식과 비슷하게 만들기 위해서 필요해졌다.
// Case 1. 컴퓨터에게 편한 방식
// assembly === 절차 지향적 언어
메모리 0 - 카운터 할당 = 0
메모리 1 - 카운터 증가
메모리 2 - 출력 'hongsik'
메모리 3 - 카운터와 원하는 반복 횟수 비교
메모리 4 - 카운터 === 원하는 반복 횟수 false? 메모리 1
// 메모리 0 ~ 3을 for문을 통해 반복한다.
// Case 2. 은행 송금 기능
메모리 0 - 송금 주소 할당 = 0000000000
메모리 1 - 전달 받은 주소의 정보를 조회
메모리 2 - 16글자가 넘어서.. 그 다음 메모리 조회
메모리 3 - 16글자가 넘어서.. 그 다음 메모리 조회
...
메모리 10 - 전달 받은 주소 정보 조회 끝!
메모리 11 - 전달 받은 주소로 송금하기 메모리 1259124 조회
하드디스크 1 - ? 아니네
하드디스크 2 - ? 아니네
// Case 3 객체 지향 프로그래밍
// => 컴퓨터 왜 쓰나요? 게임 ,일, => 편할려고, 좀 더 쉽게
// => 개발 => 상업적 가치
// => 효율적으로 해야 한다. 사람이 쓸 수 있게 개발해야 한다.
// 기계적 사고방식이 너무 어려웠기 때문에
// 사람이 사고하는 방식과 비슷하게 만들기 위해서 필요해졌다.
class 은행계좌 {
constructor(){
}
은행계좌주소: string
송금 : () => {
송금에 필요한 코드
}
입금 : () => {
입금에 필요한 코드
}
}
설명할 줄 안다 기준
A - 주장
R - 근거
E - 예시
Relations of class constructor, prototype, instance
어떻게 서로를 참조
하는지 그림으로 그려보자.
참조한다
메모리 주소(refeence) 값을 가리키고 있다
관계
1번 코드
class Humam를 생성한다.
그 안에 속성(name
, age
)과 메소드(sleep()
)를 정의한다.
2번 코드
new 연산자를 사용하여 인스턴스를 생성한다.new Human('kimcoding, 30)
Human의 이름은 'kimcoding', 나이는 30살.
2번 코드를 작성함과 동시에(new Human('kimcoding', 30
), __proto__
가 자동으로 생성된다.
Human.prototype
new 연산자를 사용하여 인스턴스(kimcoding
)를 호출할 때,
속성
과 메소드
를 전달해줄 수 있는 객체
class 내부에 constructor
내부의 속성
과 하단의 메소드
가 적혀있긴 하지만, Human.prototype
내부에 있다고 보는 것이 맞다.
constructor
속성을 인스턴스
로 전달해주는 일련의 코드
메소드
인스턴스
에는 메소드 관련 정보가 담겨있지 않다.
따라서, __proto__
가prototype chaining
을 통해서 해당 메소드에 접근할 수 있음
즉, 메소드 관련 정보
가 담겨있음
__proto__
(kimcoding.__proto__
)
dunder proto
new 연산자를 사용하여 인스턴스(kidmcoding
)를 호출할 때, 자동으로 생기는 '객체'
참조 자료형인 객체(kimcoding.__proto__
)는 prototype chaining
을 통해서
메소드 sleep
을 찾기 위해 Human.prototype
을 참조한다.
따라서, 인스턴스
에는 메소드 관련 정보가 담겨있지 않지만메소드 sleep()
을 호출할 수 있다.
Human.prototype === kimcoding.proto;
뜻
kimcoding
은 __proto__
객체를 거쳐서 Human.prototype
을 참조한다.
결과
따라서 이 코드는 true
가 된다.
Human.prototype.sleep === kimcoding.sleep;
뜻
kimcoding
인스턴스에 메소드(sleep()
)이 없기 때문에,
__proto__
객체를 거쳐서 이 주소가 Human.prototype
으로 간다.
이러한 prototype.chaining
을 통해 Human.prototype.sleep
을 참조한다.
결과
따라서 이 코드는 true
가 된다.
Human.prototype.constructor === Human;
뜻
클래스(Human
)안에 prototype(Human.prototype
)이라는 객체가 연결되어 있다.
이 객체 안에 constructor
라는 속성(주소)를 만들었다.
이 주소(Human.prototype.constructor
)는 Human
을 가리킨다(참조한다).
역할
Human을 new로 호출했을 때, 속성을 인스턴스 객체로 전달하는 역할을 한다.
결과
constructor라는 속성은 Human과 같다.
따라서 이 코드는 true
가 된다.
Human.constructor
결과
따라서 이 코드는 {[ native code ]}가 된다.
native code
'그런건 없다'고 생각하면 된다.
요약 ***
클래스가 인스턴스를 호출할 때, 클래스.prototype을 거쳐서 속성을 전달해준다.
반드시 new 연산자를 사용해야 한다.
이때 호출된 인스턴스에는 메소드 정보가 담겨있지 않기 때문에,
인스턴스는 호출 시 자동 생성된 __proto__
을 거쳐서 '클래스.prototype'을 참조하여 메소드를 호출할 수 있다. 이때, '클래스.prototype'은 '클래스.prototype.constructor'를 통해 클래스를 참조한다.
코드
// 1번 코드
class Human {
constructor(name, age) {
this.name = name;
this.age = age;
}
sleep() {
console.log(`${this.name}은 잠에 들었습니다`);
}
}
// 2번 코드
let kimcoding = new Human('김코딩', 30);
// 실습해보세요
// 실습1
Human.prototype.constructor === Human; // 결과는 무엇일까요? true
// 실습2
Human.prototype === kimcoding.__proto__; // 결과는 무엇일까요? true
// 실습3
Human.prototype.sleep === kimcoding.sleep; // 결과는 무엇일까요? true
Author And Source
이 문제에 관하여([JS/node] prototype), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@djdu4496/prototype-JavaScript저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)