일곱번쨰편 /여덟번째편
============================
이제 본격적인 일곱번째편 내용!!!
==================
6번 문제
function Child(aa,bb){
if(this.constructor !== Child)new Child();
this.aa = aa;
this.bb = bb;
}
function Parent(){
if(this.constructor !== Parent)new Parent();
}
Parent.prototype.a = [1];
Parent.prototype.f = function(){
this.a.push(this.a.length+1);
}
Child.prototype = new Parent();
Child.prototype.f = function(){
this.a.push(this.a.length*2);
}
Child.prototype.constructor = Child
var p = new Parent();
var c = new Child();
p.f();
c.f();
console.log(p.a);
console.log(c,a);
6번 문제 풀이>>>>
function Child(aa,bb){
if(this.constructor !== Child)new Child(); //이건 왜 만들어 놓았냐면 new 를 안했을경우 방지책으로 코드를 수정해주는 기능을 만들어놓은것임! 즉, this의 컨스트럭터가 차일드랑 같지않을경우에 뉴차일드로 수정시켜주는것임!
this.aa = aa;
this.bb = bb;
}
function Parent(){
if(this.constructor !== Parent)new Parent();
}
Parent.prototype.a = [1];
Parent.prototype.f = function(){
this.a.push(this.a.length+1);
}
Child.prototype = new Parent();
Child.prototype.f = function(){
this.a.push(this.a.length*2);
}
Child.prototype.constructor = Child //이부분도 다시 연결해주는작업을해야 차일드컨스트럭쳐를 안잃어버린다.
var p = new Parent();
var c = new Child();
p.f();
c.f();
console.log(p.a);
console.log(c,a);
다른 문제>>>>
function Child(){};
Child.prototype.c ={};
var c1 = new Child();
var c2 = new Child();
Child.prototype.a = true;
c1.a; //true
c2.a; // true
다른문제>>
Object.prototype.b = true;
c1.b; // true
c2.b; // true
({}).b; // true
다른문제>>
Child.prototype = {
c:{}
}
var c3 = new Child();
c1.c === c3.c //false
자바스크립트는 객체지향 언어인가?
-이에대한 답은 사실,,,
자바 같은경우 클래스 개념이 있다.
그리고 최근에 자바스크립트도 es6에서 클래스개념이 도입되긴했다.
아무튼 클래스개념이 있어야 객체지향언어이다 라고 하는 말도 있는데,
자바스크립트는 처음부터 없었으니 객체지향언어가 아닌가?
아니다, 자바스크립트도 객체지향적 언어에 속한다.
왜냐면
어떤언어든 객체를 만들수 있으면 객체지향 언어라고 말할수 있기 떄문이다.
자바스크립트는 객체를 만들수있다.
자바스크립트에서 객체를 만드는방법 즉,생성방법은 그냥
중괄호를 이용하면 된다.
{
fn:function(){}, //매소드
hi:'안녕' // 변수
}
//이걸 객체 리터럴이라 부름//
다만 우리가 많이 보는 JAVA나 다른 객체 지향 언어와 다르게 class가 없다.(최근JS에서는 추가됨)
프로그래밍에서 중복제거가 중요함...
여튼
만약
a = {fn:function(){}}
b = {fn:function(){}}
이렇게 fn이라는 이름이 중복되는게 있는데 ,,,
이럴때 프로토타입을 이용하면 좋다.
*프로토타입 정의
-다른 객체의 기반이 되는 객체
-기본적으로 제일 상위는 Object
{}
toString , valueOf 메소드가 있음, proto
자 이런걸 어떻게
a.toString 이렇게 바로 쓸수가 있느냐? 라면
그건 이미 프로토타입이 정의가 되있기 떄문이다.
무슨 프로토타입?
Object에서 정의된 Object프로토타입을 갖다가 써서 저렇게 쓸수있는것임.
이걸 확인하는 방법도 있다.
최신브라우져 콘솔창을 열어서
빈 객체를 하나 쓰고 이걸 콜솔.dir 하면
console.dir({});
이렇게 하면
proto 라는게 콘솔에 나오는데,
이걸보면,
이안에 toString, valueOf 이런게 많이 들어있다 이런 매소드가 이미 정의되있다.이걸 쓰는거다 이용하는거다
그래서 아무튼
우리가 커스텀으로 프로토 타입을 정의하고싶을때는,,,,
new 연산자>>>>>>>>
function Person(){ // 일단 여기 함수를 하나 만든다.(이게 생성자 함수임) 그리고
this.name = 'SUN'
}
Person.prototype.getName = function(){return this.name;} // 여기에 프로토타입에다가 이렇게 원하는 넣고싶은 매소드를 정의해서 추가하면된다.
var p = new Person(); //이렇게 새로운 객체를 생성할때 new연산자를 써서 생성해야한다.
그러면 new 연산자는 어떻게 동작을 할까?
1.함수의 prototype을 proto 로 갖는 객체 생성
2.위의 객체를 this로 바인딩하고 함수실행.
3.그리고 함수의 리턴 값이 객체면 객체 반환
4.아니면 this 반환.
아무튼
여기
function Person(){
this.name = 'SUN'
}
Person.prototype.getName = function(){return this.name;}
var p = new Person();
p.getName(); // SUN
이 코드에서
Person.prototype 을 수정하지말고 더 기능을 추가하자.
function Programmer(){
this.name = 'KIM SUN'
}
Programmer.prototype = new Person();
Programmer.prototype.lang = function(){return 'JAVASCRIPT'};
var sun = new Programmer();
sun.lang(); // JAVASCRIPT
여기서 문제를 내보면,
sun.getName(); // KIM SUN
이 나온다.
왜 그러냐면
일단
sun의 proto 를 확인해보면 없다.
그리고 프로토타입을 올라타고가서
Programmer proto 에도 없다
그럼 올라타고가서
Person 의 proto 에는 등록이 되있다
거기에getName이라는 매소드가 프로토타입에 등록되어있다 this.name 이라고 바인딩되어있다 그럼
다시 처음으로 돌아가서
sun.getName(); 을 실행하면 리턴값으로 this.name 이 실행이 되는데, 이떄 this값은
앞에 쩜 한곳에서 this를 찾는다 그럼
sun 에서 찾는다는 소리다 sun은 곧 Programmer 의 프로토타입에서 등록된 this.name 의 값이 나온다.
즉, 프로토타입의 체인을 타고타고 링크를 타고 찾는다는 것이 중요하다.
근데 proto 를 타고 가서도 원하는 매소드를 못찾으면 undefined 가 뜬다.
그러면 다른문제 하나더 내자면,
그럼
delete sun.name; 을하고 sun.getName(); 을 실행하면 결과값이 무엇이 나올까?
// 답은 SUN 이 나온다.
왜냐면 프로토타입 체인을 따라가서 Person 에서 찾기 떄문이다.
그러면
한번더 delete sun.name 을 실행하고
sun.getName(); 을 실행시키면 뭐가될까?
//SUN 이 출력된다.
왜냐면
일단 delete는 프로토타입에 등록된걸 지우는 명령어가 아니다
그리고 애초에 sun에 속한 프로퍼티만 삭제하라는 명령어이다.
즉, 프로토타입체인을 가지도 안고, 어짜피 프로토타입에있는걸 지울수도없는 명령어다.
그래서 그냥 SUN 이 출력되는 거임.
자세히 말하자면,
일단 프로토타입을 읽어들일때는 쭉 체인을 타고타고 해서 읽어들이지만,
쓸때는 바로 직접적으로 쓴다.(생성)
마찬가지로 delete를 이용해서, 지운다면 모든,, 속성이 변경되는거다
그래서 그럴리는 없으므로,
지우려면
직접 접근해서 지워야한다.타고타고 이렇게 안한다.
만약
function Child(){};
Child.prototype.a = 'aaa';
var sun = new Child();
var sun2 = new Child();
sun.a = 'bbb';
이거는 뭐 타고타고 하는게아니다
쓰기 이기떄문에 그냥 sun에 생성이되는거다. 뭐가? a 가 (bbb라는 값을가진)
오늘 배운거 요약 정리
일단 new 연산자에대하여,,,
new 를 하면 어떻게 동작하냐면,
new를해서 함수를 실행시키면..객체를생성하는데, 그객체안에 뭐가들어있냐면, 그 원래 함수의 프로토타입의 proto를 가진 객체가 생성된다.
proto 가 뭐냐면 이거는 정보이다. 무슨 정보냐면 어디서 왔는가의 정보가 담겨져있다.
내출신이 어디인가, 즉 주소정보가 담겨있다.
그래서 프로토타입체인이 이걸보고 따라올라가는거다.
참고로 proto는 프로토타입은 가지고있지않고, 오리지널함수의 프로토타입의 정보를 담고 있는게 proto 이다.
즉, proto는 프로토타입은 아니다.
그래서 다시돌아가자면,
new 뭐뭐(); 이렇게 하면
이거는 일단 함수가실행된건데,
this로 바인딩되서 함수가 실행이된거다,
즉, new Person(); 하면 Person함수가 실행이되고, 이함수 실행은 proto랑 바인딩이 되서 실행이 된다.
그래서 이걸 변수로 저장해서 변수를 찍어보면,
오리지널 함수의 프로퍼티들이 바인딩되서 출력이 된다.
proto는 일종의 오리지널함수의 복사본인것이다.
그리고
프로토타입 체인을 추가하는 방법 (인위적으로 만드는 방법은)
Man1.prototype = new Person();
이런식으로 추가를해서 체인을 형성하게끔 할수있다.
그래서 프로토타입에 등록된 속성을 찾는 과정이 어떻게 되냐면,
우선 자기 자신의 속성을 막 뒤져서 찾고, 없으면 체인을 타고(proto) 찾고 이런식이다.
참고 자료
function Parent(){
this.a = 1;
};
Parent.prototype.a = [2];
Parent.prototype.f = function(){return this.a.push(9);}
var x = new Parent();
이렇게 세팅한 코드가 있다.
일단
Parent라는 객체 생성함 (생성자함수를통해 )
그안에 this.a 변수 생성 (이건 계속해서 로컬 변수a로 바인딩됨)
그리고
프로토타입에 a라는 매소드도 생성함
그럼 일단 a가 중복된상황인데 사실 중복은 아님 (겹치지 않으니까)
그래서
그밑에 코드는 프로토타입 a를 수정하는 코드임
그래서 x로 해서
x.a 를 하면 바로 this.a 로바인딩되서 1 이나옴 즉, 로컬 변수로 바인딩됬다는 말임
만약 x.a를 했을때 this.a 가 없었다면 [2] 이게 나왔을것임
그래서 delete x.a 를 하면 로컬변수a가 삭제가 되고
x.a를 찍어보면
[2] 가 바인딩되서 출력됨
즉, 프로토타입에 등록된 애가 나오는거임
그래서 수정코드도 실행시키면 동작 잘됨.
요약하자면
this로 바인딩된건 지워야 프로토타입으로 된게 나온다는것임.