오늘 공부한 내용 proto, prototype ???? 기억도 잘 나지 않는 ㄷ ㅏ......
다시 보면서 하나하나 복습해보자...............
prototype
JavaScript는 Class 라는 개념이 없다. 그래서 기존의 객체를 복사(Cloning) 하여 새로운 객체를 생성하는 prototype 기반의 언어이다. prototype 기반 언어는 객체 원형인 prototype을 이용하여 새로운 객체를 만들어 낸다. 이렇게 생성된 객체도 또 다른 객체의 원형이 될 수 있다. prototype은 객체를 확장하고 객체 지향적인 프로그래밍을 가능하게 함.
prototype은 크게 두가지로 해석 됨
1. prototype 속성
2. proto 속성 (객체멤버)
요 두가지의 차이를 이해하려면 JS의 함수와 객체 내부적인 구조를 이해해야 함
1. 함수와 객체의 내부 구조
JavaScript에서는 함수를 정의하고 *파싱단계에 들어가면, 내부적으로 수행되는 작업이 있다. 함수 멤버로 prototype속성이 있다. 이 속성은 다른 곳에 생성된 함수이름의 prototype Object, 프로토타입 객체를 참조한다. prototype 객체의 멤버인 constructor 속성은 함수를 참조하는 내부 구조를 가진다.
*파싱(parsing: 구문 분석)은 하나의 프로그램을 런타임 환경(예를 들면, 브라우저 내 자바스크립트 엔진)이 실제로 실행할 수 있는 내부 포맷으로 분석하고 변환하는 것을 의미
function Person(){} 요 함수를 생성하면 1. 함수 2. prototype Object 가 생김
[참고 1]
속성이 하나도 없는 function Person(){} 함수가 정의되고 파싱단계에 들어가면, Person함수 prototype 속성은 prototype Object, 프로토타입 객체를 참조한다. prototype 객체 멤버인 constructor 속성은 Person 함수를 참조한다.
* Person 함수의 prototype 속성이 참조하는 prototype Object 는 new 라는 연산자와Person 함수를 통해 생성된 모든 객체의 원형이 되는 Object 이다. 생성된 모 ~ 든 객체가 참조한다는 것을 기억하자
function Person(){} ////// Person 함수
var joon = new Person(); ////// Person 프로토타입 객체
var jisoo = new Person();
[참고 2]
JavaScript 에서 기본 데이터 타입인 boolean, number, string, 그리고 null, undefined 빼고 모두 객체이다. 사용자가 정의한 함수도, new 연산자를 통해 생성된 것도 모두 객체.
이러한 모든 객체들 안에는 proto(비표준) 속성이 있다. 이 속성은 객체가 만들어지기 위해 사용된 원형인 prototype object 를 숨은 링크로 참조하는 역할을 한다.
2. Prototype Object, 프로토타입 객체란?
함수를 정의하면 다른 곳에 생성되는 prototype Object는 자신이 다른 객체의 원형이 되는 객체이다. 모든 객체는 prototype Object에 접근할 수 있다. Prototype Object도 동적으로 런타임에 멤버를 추가할 수 있다. 같은 원형을 복사로 생성된 모든 객체는 추가된 멤버를 사용할 수 있다. (무슨말일까)
* runtime : Runtime is a general term that refers to any library, framework, or platform that your code runs on.
function Person(){}
var joon = new Person();
var jisoo = new Person();
Person.prototype.getType=function(){
return "인간" ;
}
console.log(joon.getType()); //인간
console.log(jisoo.getType()); //인간
console 로 분석해보기
-> 서로 참조하는 기술 함수형x 객체지향x -> 프로토타입 기반으로 -> 성능 저하.... 무한loop...
[참고 3]
function Person(){}
var joon = new Person();
var jisoo = new Person();
Person.prototype.getType=function(){
return "인간" ;
}
joon.getType = function(){
return "내가 쭌이야";
}
console.log(joon.getType()); // 내가 쭌이야
console.log(jisoo.getType()); //인간
jisoo.age = 25;
console.log(joon.age); //undefined
console.log(jisoo.age); //25
아하 아까 수업 중에 들은게 어렴풋이 생각이 난다. 부모객체 (?) 의 prototype.__속성값___을 변경해주면 이를 원형으로 삼은 모든 자녀 객체인 var STH = new Person(); , STH 객체들이 변하고 각각 객체에 .___속성값___= xxx; 변경해주면 그것만 변하는거구나 (변하는게 아닌 개인 객체에 해당 속성을 추가하는 것이었음)
함수 안의 prototype 속성을 이용하여 멤버를 추가함. prototype Object 에 getType() 함수를 추가하면 멤버를 추가하기 전 생성된 객체 (joon, jisoo) 에서도 추가된 멤버를 사용할 수 있다.
Prototype Object에 멤버를 추가,수정,삭제할 때는 함수 안의 prototype 속성을 사용해야 하지만 prototype 멤버를 읽을 때는 함수 안의 prototype속성 또는 객체 이름으로 접근한다.
--------------------------------------------------------여기까지의 JS ----------------------------------------------------------
function Person(){};
var joon = new Person();
var jisoo = new Person();
Person.prototype.getType=function(){
return '인간';
}
console.log(joon.getType()); //'인간'
console.log(jisoo.getType()); //'인간'
joon.getType=function(){
return '나는 joon이다.';
}
console.log(joon.getType()); //'나는 joon이다.'
console.log(jisoo.getType()); //'인간'
jisoo.age=25;
console.log(joon.age); // undefined
console.log(jisoo.age); // 25
Person.prototype.getType = function(){ //다시 prototype.getType을 바꿔도
return '사람';
}
console.log(joon.getType()); // '나는 joon이다.' //joon 은 개인 객체 속성으로 가진걸로 쓴다.
console.log(jisoo.getType()); // '사람'
요 결과들을 잘 보면 이해가 간다
joon.getType=function(){
return '나는 joon이다.';
}
joon 이라는 객체를 이용하여 getType() return 값을 ' 나는 joon이다'로 수정함. 이는 Person Prototype Object 의 멤버를 수정한 것이 아니라 자신의(joob) 객체에 멤버를 추가한 것이다. joon객체로 getType()을 호출하면 protptype getType()을 호출한 것이 아니고 본인의 객체 멤버를 호출한 것.
Person.prototype.getType = function(){
return '사람';
}
console.log(joon.getType()); // 내가 쭌이다.
console.log(jisoo.getType()); //사람
Prototype의 객체 멤버를 수정하는 경우 위와 같다. 이렇게 수정해도 joon.getType()은 본인이 해당 속성 (멤버) ㅇ ㅣ있다면 먼저 자신의 멤버를 호출한다.
Prototype = 새로운 객체가 생성되기 위한 원형이 되는 객체
같은 원형으로 생성된 객체가 공통으로 참조하는 공간. prototype Object의 멤버를 읽는 경우 객체 or 함수의 prototype 속성을 통해 접근할 수 있다. 하지만 추가, 수정, 삭제의 경우 prototype 속성을 통해 접근해야 한다
2. Prototype, 프로토타입이란?
JavaScript 에서 기본 데이터 타입을 제외한 모든 것이 객체. 객체가 만들어지기 위해 자신을 만드는데 사용된 원형인 Prototype Object를 이용하여 객체를 만든다. 이 때 만들어진 객체 안에는 __proto__(비표준) 속성이 있고 이 속성이 자신을 만들어낸 원형을 의미하는 Prototype Object를 참조하는 숨겨진 링크가 있다. 이 링크를 Prototype이라고 한다.
function Person(){}
var joon = new Person();
joon 객체의 멤버인 __proto__ (비표준) 속성이 prototype object를 가리키는 숨은 링크를 prototype이라고 한다. Prototype은 크게 두 가지로 해석된다.
- 함수 멤버인 prototype 속성은 prototype object를 참조하는 속성
- 함수와 new 연산자가 만나 생성한 객체의 prototype object를 지정해주는 역할
객체 안의 __proto__(비표준) 속성은 자신을 만들어낸 원형인 prototype object 를 참조하는 숨겨진 링크로써 prototype을 의미한다. JavsScript에서는 숨겨진 링크가 있어 prototype object 멤버에 접근할 수 있다. 그래서 이 prototype link 를 사용자가 정의한 object 객체에 링크가 참조되도록 정하면 코드의 재사용과 객체 지향적인 프로그래밍이 가능하다.
4. 코드의 재사용
class 개념이 있는 JAVA에서는 중복된 코드를 상속받아 코드 재활용이 가능하지만 JavaScript에서는 클래스가 없는, prototype 기반 언어이다. prototype 을 이용하여 코드 재사용이 가능하다.
- classical 방식
new 연산자를 통해 생성한 객체를 사용하여 코드를 재사용 (JAVA와 유사함)
- prototypal 방식
리터럴 or Object.create() 을 이용하여 객체를 생성하고 확장해가는 방식 (JS는 요걸 더 선호, 이유 : 간결)
4-1. 기본 방법
부모에 해당하는 함수를 이용하여 객체 생성, 자식에 해당하는 함수의 prototype 속성을 부모 함수를 이용하여 생성한 객체를 참조하는 방법
function Person(name) { // 부모 함수
this.name = name || "혁준";
}
Person.prototype.getName = function(){
return this.name;
}
function Korean(name){} // 자식 함수
Korean.prototype = new Person();
var kor1 = new Korean();
console.log(kor1.getName());
var kor2 = new Korean("지수");
console.log(kor2.getName());
자식함수인 Korean 함수 안의 prototype 속성을 부모 함수로 생성된 객체로 바꿨다. Korean 함수와 new 연산자로 생성된 kor객체의 __proto__ 속성이 부모 함수를 이용하여 생성된 객체를 참조.
즉, Person 함수 (부모함수) 의 prototype property = Korean 함수를 이용하여 생성된 모든 객체의 Prototype Object가 된다.
kor1,kor2에는 getName()이라는 속성이 없지만 부모에 해당하는 prototype Object에 name이 있다. 이 prototype Object의 부모에 getName()을 가지고 있어 kor1,kor2가 사용할 수 있다.
단점 : 부모 객체의 속성과 prototype 속성을 모 ~ 무 물려받게 된다. 대부분의 경우 객체 자신의 속성은 특정 인스턴스에 한정되어 재사용할수 없어 필요가 없다.
또한, 자식 객체를 생성할 때 parameter 인자를 넘겨도 부모 객체를 생성할 때 인자를 넘겨주지 못한다.
객체를 생성할 때마다 부모의 함수를 호출할 수 있지만 매우 비효율 적임.
-> 이를 보완한 ↓↓↓↓
4-2. 생성자 빌려쓰기
이 방법은 기본 4-1. 문제점인 자식 함수에서 받은 인자를 부모 함수 인자로 전달하지 못한 부분을 해결한다. 부모의 함수의 this에 자식 객체를 바인딩하는 방식
function Person(name){
this.name = name || "혁준";
}
Person.prototype.getName = function(){
return this.name;
}
function Korean(name){
Person.apply(this, arguments);
}
var kor1 = new Korean('지수');
console.log(kor1.name); //지수
Korean 함수 내부에서 apply 함수를 이용. 부모객체인 Person 함수 영역의 this를 Korean 함수 안의 this로 바인딩.
이것은 부모의 속성을 자식함수 안에 모두 복사한다. 객체를 생성하고 name을 출력한다. 생성자 빌려쓰기는 부모객체 멤버를 복사하여 자신의 것으로 만들어 버린다는 차이점이 있다.
단점 : 부모객체의 this로된 멤버들만 물려받게 된다는 단점이 있다. 그래서 부모객체의 prototype object 의 멤버들을 물려받지 못한다.
4-3. 생성자 빌려쓰고 prototype 지정해주기
이 방법은 방법1,2 문제점들을 보완하며 JAVA에서 예상할 수 있는 동작 방식과 유사
function Person(name){
this.name = name || "혁준";
}
Person.prototype.getName= function(){
return this.name;
}
function Korean(name){
Person.apply(this,arguments);
}
Korean.prototype= new Person();
let kor1 = new Korean ('지수');
console.log(kor1.getName());
부모 함수 this를 자식 함수 this로 바인딩함.
위 글 내용 & 사진 출처 사이트 www.nextree.co.kr/p7323/
============================================================================
학원 수업 내용
function Person(){
this.eyes=2;
this.nose=1;
}
let kim = new Person();
let park = new Person();
console.log(kim.eyes);
console.log(kim.nose);
console.log(park.eyes);
console.log(park.nose);
park.eyes=4;
console.log('---------');
console.log(kim.eyes);
console.log(kim.nose);
console.log(park.eyes);
console.log(park.nose);
우리가 사용하는 모든 함수는 proto 안에 들어가 있음. 저 property를 사용할 수 있음.
---------------------------------------------------------------------------------------------------------------
function Person(){}
Person.prototype.eyes=2;
Person.prototype.nose=1;
let kim = new Person();
let park = new Person();
kim, park 안의 내용은 없다. 그냥 Person 의 객체라서
Person 의 prototype Object 속성안에 있는 값들을 kim, park 의 proto 안에 있음.
kim, park 은 자기 안에서 값을 찾고 없으면 하위에 있는 __proto__에 가서 값이 있으면 쓰고 없으면 다음 __proto__에 가서 값을 찾는다.
function Person(){}
Person.prototype.eyes=2;
Person.prototype.nose=1;
let kim = new Person();
let park = new Person();
console.log(kim.eyes);
console.log(kim.nose);
console.log(park.eyes);
console.log(park.nose);
console.log('-----------------------')
park.eyes = 4;
console.log(kim.eyes);
console.log(kim.nose);
console.log(park.eyes);
console.log(park.nose);
console.log('-----------------------')
park.__proto__.eyes = 4;
console.log(kim.eyes);
console.log(kim.nose);
console.log(park.eyes);
console.log(park.nose);
park.eyes = 4; park only
park.__proto__.eyes = 4; -> 모든 Objects of Person 의 멤버 eyes의 값이 바뀐다.
__proto__ -> Person Prototype Object 의 속성값을 가지고 있음.
------------------------------------------------------------------------------------------------------------------------------
Prototype link = __proto__
Prototype Object = protptype
>??
protptype이란 -> prototype이 가르키는 Prototype Object를 가르키는 Link
function Person(){
this.eyes=2;
this.nose=1;
}
let kim = new Person();
let park = new Person();
console.log(kim);
console.log(park);
console.log(kim.eyes);
console.log(kim.nose);
console.log(park.eyes);
console.log(park.nose);
console.log('---------------');
kim.eyes = 3;
park.nose=4;
console.log(kim);
console.log(park);
console.log(kim.eyes);
console.log(kim.nose);
console.log(park.eyes);
console.log(park.nose);
function Person(){ this.eyes = 2;} vs function Person(){} Person.prototype.eyes=2; 의 차이
function Person(){
this.eyes=2;
this.nose=1;
}
let kim = new Person();
let park = new Person();
console.log(kim);
console.log(park);
console.log(kim.eyes);
console.log(kim.nose);
console.log(park.eyes);
console.log(park.nose);
console.log('---------------');
kim.eyes = 10;
console.log(kim.eyes);
console.log(kim.nose);
console.log(park.eyes);
console.log(park.nose);
console.log('---------------');
park.__proto__.nose = 10; // 불가
console.log(kim.eyes);
console.log(kim.nose);
console.log(park.eyes);
console.log(park.nose);
console.log('---------------');
function Person2(){};
Person2.prototype.eyes=2;
Person2.prototype.nose=1;
let kim2 = new Person2();
let park2 = new Person2();
console.log(kim2);
console.log(park2);
console.log(kim2.eyes);
console.log(kim2.nose);
console.log(park2.eyes);
console.log(park2.nose);
console.log('---------------');
kim2.eyes = 10; // kim2 객체 안 eyes 멤버 추가 ( 변경x )
// -> 본인 것을 먼저 사용
console.log(kim2.eyes);
console.log(kim2.nose);
console.log(park2.eyes);
console.log(park2.nose);
console.log('---------------');
park2.__proto__.nose = 10; //전체 공유하는 prototype object 의 속성 변경
console.log(kim2.eyes);
console.log(kim2.nose);
console.log(park2.eyes);
console.log(park2.nose);
---------------------------------------------------------------------------------------------------------------------
new = 생성자 => 저 함수를 객체로 만들겠다 ~
함수에서 객체로 변환하려면 new 가 필요함
객체는 이미 객체이므로 new를 붙힐 수 없음
function Person(){ //함수 객체
this.eyes=2;
this.nose=1;
}
const Person2 ={ // 그냥 객체
eyes:2,
nose:1
}
function Person(){};
Person.prototype.eyes=2;
Person.prototype.nose=1;
let kim = new Person();
let park = new Person();
-------------------------------------------------------------------------------------------------------------------------------
let foo1 = {name:'foo'};
function foo2(){
this.name='foo';
}
foo3 = function (){
this.name='foo';
}
foo4 = ()=>{
this.name='foo';
}
console.log(foo1);
console.log(foo2);
console.log(foo3);
console.log(foo4);
익명함수는 (foo4) __proto__ 가 없다 .
function foo(){};
foo.prototype.text='hello';
let Obj = new foo();
console.log(Obj);
질문 1
다시 볼 것
function foo(){};
foo.prototype.text='hello';
let Obj = new foo();
console.dir(Obj.text); ok
console.dir(Obj.constructor); ok
console.dir(foo); //얘는 이해가 안가네
console.dir(foo.prototype); ok
console.log(Obj); ok
console.log(Obj.__proto__); ok
---------------------------------------------------------------L I N K-----------------------------------------------------------
prototype link 라는 것은 내가 값이 없을 때 proto 를 참조 한다. 찾을 때까지 계쏙 내려감. 정말로 없으면 undefined 가 나온다.
let x = {number1:1}
let y = {number2:2}
let z = { //요 방법을 심플하게 바꾸기
'x':x,
'y':y
}
z.x.number1 = 3;
let x = {number1:1}
let y = {number2:2}
let z = {};
x.__proto__=y;
z.__proto__=x;
console.log(z);
console.log(z.number1);
console.log(z.number2);
let x = {number1:1}
let y = {number2:2}
let z = {};
x.__proto__=y;
z.__proto__=x;
y.number2 = 5;
z.number2 = 10;
y.number1 = 11;
console.log(c.number1) 나오도록
-------------------------------------------------------------------------------------------------------------------------
let user = {name:"emily"}
check console
user 안에 proto 객체 안에 많은 함수들을 사용할 수 있다.
name = property 값
질문 2
---------------------------------------------------------------------------------------------------------------------
const 아반떼 = {
색상:'블루',
휠:'4',
네비게이션:true,
drive(){
console.log('시동');
}
}
const 소나타 = {
색상:'레드',
휠:'4',
네비게이션:false,
drive(){
console.log('시동');
}
}
const 아반떼 = {
색상:'검정',
휠:'4',
네비게이션:true,
drive(){
console.log('시동');
}
}
drive(){console.log('시동')} = drive:function(){console.log('시동')} 과 같다.
겹치는 내용 : drive(){}, 휠 2가지
const 자동차 = {
휠:'4',
drive(){
console.log('시동');
}
}
const 아반떼 = {
색상:'블루',
네비게이션:true,
}
const 소나타 = {
색상:'레드',
네비게이션:false,
}
const 제네시스 = {
색상:'검정',
네비게이션:true,
}
아반떼.__proto__=자동차;
소나타.__proto__=자동차;
제네시스.__proto__=자동차;
=
일반 객체를 사용하듯 __proto__:값 이렇게 써도 된다.
const 자동차 = {
휠:'4',
drive(){
console.log('시동');
}
}
const 아반떼 = {
색상:'블루',
네비게이션:true,
__proto__:자동차
}
const 소나타 = {
색상:'레드',
네비게이션:false,
__proto__:자동차
}
const 제네시스 = {
색상:'검정',
네비게이션:true,
__proto__:자동차
}
--------------------------------같은 것을 prototype object -> prototype을 가지고 해보기 ----------------------------------
const 자동차 = function(컬러, 네비게이션){
this.컬러 = 컬러;
this.네비게이션 = 네비게이션;
}
자동차.prototype.휠 = 4;
자동차.prototype.dirve = function(){
console.log('drive');
}
let 아반떼 = new 자동차 ('레드',true);
let 소나타 = new 자동차 ('블루',true);
let 제네시스 = new 자동차 ('검정',true);
function 자동차(){
this.색상='블루';
this.네비게이션=false;
this.휠='4';
this.drive=function(){
console.log('시동');
}
}
let 아반떼 = new 자동차();
let 소나타 = new 자동차();
let 제네시스 = new 자동차();
- > 메모리에 안좋을 것 같은 ? 같은 내용 반복
function 자동차(색상, 네비게이션){
this.색상=색상;
this.네비게이션=네비게이션;
this.휠='4';
this.drive=function(){
console.log('시동');
}
}
let 아반떼 = new 자동차('블루', true);
let 소나타 = new 자동차('레드', false);
let 제네시스 = new 자동차('검정', true);
같은 내용 '부품' 이라는 객체로 만들어 각 객체의 proto 안에 넣기
let 부품 = {
휠:'4',
drive:function(){
console.log('시동');
}
}
function 자동차(색상, 네비게이션){
this.색상=색상;
this.네비게이션=네비게이션;
}
let 아반떼 = new 자동차('블루', true);
let 소나타 = new 자동차('레드', false);
let 제네시스 = new 자동차('검정', true);
아반떼.__proto__=부품;
소나타.__proto__=부품;
제네시스.__proto__=부품;
proto 대신 prototype 을 사용하여 공통 반환 -> 결과값이 많아도 쉽게 처리 가능
function 자동차(색상, 네비게이션){
this.색상=색상;
this.네비게이션=네비게이션;
}
let 아반떼 = new 자동차('블루', true);
let 소나타 = new 자동차('레드', false);
let 제네시스 = new 자동차('검정', true);
자동차.prototype.휠='4';
자동차.prototype.drive=function(){
console.log('drive');
}
----------------------------------------------------------CLASS------------------------------------------------------------
class Car{
constructor(color){
this.color=color;
this.wheels=4;
}
driver(){
console.log('drive');
}
stop(){
console.log('stop');
}
}
class avante extends Car{
showName(){
console.log('아반떼');
}
}
const 아반떼 = new avante('blue');
과제
prototype , __proto__로 위와 똑같이 만들기
//prototype//
function avante(color){
this.color=color;
this.wheels=4
}
avante.prototype.showName=function(){
console.log('아반떼')
}
let x = {
drive:function(){
console.log('drive');
},
stop:function(){
console.log('stop')
}
}
avante.prototype.__proto__=x;
let 아반떼 = new avante('blue');
질문 3 ok
//prototype//
function avante(color){
this.color=color;
this.wheels=4
}
avante.prototype.showName=function(){
console.log('아반떼')
}
function x(){}
x.prototype.drive = function(){}
x.prototype.stop = function(){}
avante.prototype.__proto__= new x().__proto__;
let 아반떼 = new avante('blue');
이렇게 하면 constructor 가 생긴다.
'블록체인 기반 핀테크 및 응용 SW개발자 양성과정 일기' 카테고리의 다른 글
[35일차 복습 및 정리] JavaScript try... catch... finally 란? 사용법, 특징, 예외처리, throw도 함께 써보기 연습 (0) | 2021.05.01 |
---|---|
[35일차 20210430] 비동기 / 동기 / 콜백함수 / promise / promise.all / async await (0) | 2021.04.30 |
[34일차] 20210429 proto prototype Object etc (0) | 2021.04.29 |
[33일차 복습 및 정리] node.js connection pool 이란? 노드 제이에스 커넥션 사용법 (0) | 2021.04.28 |
[33일차] 20210428 node.js connection pool 이론 / 코드 (0) | 2021.04.28 |