멋진인생님 블로그참조

http://run2you.tistory.com/12

javascript prototype 이란 무엇인가???? (1부)

Posted 2008/06/16 01:51

최신 배포된 자바스크립트 프레임 워크들에 관심을 가지고 소스를 보다보면

prototype 이란게 나옵니다….

여기서 prototype 이란 prototype.js 의 prototype 하곤 틀린것입니다.  그럼 prototype 이란 무엇

이고 어떻게 써야 할건가 이번 시간에 한번 보도록 하죠..(무슨 선생님 같습니다 -_-;;;;;)

 

  1. var man = function(name){  
  2.      this.name = name;  
  3. }  
  4.   
  5. var niceguy = new man(‘멋진인생’);  
  6.   
  7. alert(niceguy.name);  

생성자 함수를 사용하여 객체를 하나 생성했습니다. 객체의 프로퍼티에 접근하기 위해선

상기 소스 처럼 사용해도 되나.. 우리는 인스턴스 메소드를 사용해서 name 을 가져오는

getName 메소드를 만들어 보도록 할겁니다.

  1. var man = function(name){  
  2.      this.name = name;  
  3.      this.getName = function(){  
  4.         alert(this.name);  
  5.      }  
  6. }  
  7.   
  8. var niceguy = new man(‘멋진인생’);    
  9. niceguy.getName();  
  10.   
  11. var panda     = new man(‘쿵후팬더’);    
  12. panda.getName();     

 자 멋지게 된거 같죠!!  그러나 사실 잘보시면 알겠지만 객체 마다 name 프로퍼티와 getName

 메소드가 포함되어 있습니다.. 사실 name 프로퍼티는 각 객체 마다 값이 틀리지만 getName

 메소드는 동일한 메소드이기 때문에 사실 객체마다 메소드가 존재해서 부피를 키우는 꼴이 되는

거죠.. 그럼 다른 방법은 없을까요..

  1. var man = function(name){  
  2.      this.name = name;  
  3. }  
  4.   
  5. var getName = function(){  
  6.       alert(this.name);  
  7. }    
  8.   
  9. var niceguy = new man(‘멋진인생’);    
  10. getName.call(niceguy);  
  11.   
  12. var panda     = new man(‘쿵후팬더’);    
  13. getName.call(panda);    

자 멋지게 된거 같죠!! 근데 사실 이렇게 함수로 빼서 call, apply 등으로 사용하게 되면, 일단

하나의 함수로 다같이 사용하는건 맞습니다. 맞고요~~ 근데 이렇게 되었을시 일단 지저분하고,

메소드가 계속 추가 되었을시 관리는 누가 하나요???(전 못합니다 -_-;;;)

사실 모듈화된 javascript 를 잘 만들려면

객체형식으로 분리해서 관리 하여야 합니다.. 이제 최종적으로 수정해 볼까요..

  1. var man = function(name){  
  2.      this.name = name;  
  3. }  
  4.   
  5. man.prototype.getName = function(){  
  6.     alert(this.name);  
  7. }  
  8.   
  9. var niceguy = new man(‘멋진인생’);    
  10. niceguy.getName();  
  11.   
  12. var panda     = new man(‘쿵후팬더’);    
  13. panda.getName();  

뭔지 모르겠지만 일단 잘 작동 합니다….

도대체 무슨일이 일어 난걸까요??? 살짝 흥분도 됩니다(저 혼자)

사실 function 함수 엔 Prototype 객체를 가르키는 prototype 이란 프로퍼티가 하나 존재합니다.

이 Prototype 객체에 공유되어  있는 프로퍼티와 메소드가 객체 생성시 해당 생성자 function 으로

생성한 모든 인스턴스에서 공유됩니다…

글이 길어지고 밤도 깊어지므로 더 자세한 내용은 2부로 넘기도록 하겠습니다..

회사에서 막간을 이용해 글을 이어 나가 봅니다..

모든 function 에는 Prototype 객체를 가르키는 prototype 이라는 프로퍼티가 있다고 했습니다.

그럼 그 prototype 에는 사실 딱 하나의 프로퍼티가 존재 합니다.

그 이름 하여 constructor 입니다..  

   

  1. var man = function(name){  
  2.     this.name = name;  
  3.     this.getName = function(){  
  4.         alert(this.name);  
  5.     }  
  6. }  
  7.   
  8. alert(a.prototype.constructor);  

해당 prototype의 constructor 는 prototype 을 가지고 있는 function 을 가르킵니다.

일단 이부분은 나중에 다시 설명하도록 하고

이전 글 마지막에서 보았듯이 어떻게 prototype 에서 각 객체의 인스턴스로 프로퍼티들을 공유 할까

요… 그건 상속과도 비슷한 개념입니다…

   

  1. var man = function(name){  
  2.     this.name = name;  
  3. }  
  4.   
  5. man.prototype.getName = function(){  
  6.         alert(this.name);                     
  7. }  
  8.   
  9.   
  10. var niceguy = new man(“멋진인생”);  
  11. niceguy.getName();  

상기 소스를 보시면 man 생성자 함수를 통하여 객체를 생성했습니다.

niceguy 인스턴스에는 분명 getName 이 존재 하지 않으나 getName 은 정상적으로 작동하게 되죠.

사실 원리는 이렇습니다.. 최초 호출시 man 자체에서 getName을 찾아 봅니다.

당연히 없겠죠.. 그럼 man.prototype 에서 getName 을 찾아 봅니다. 물론 있습니다.. 그럼 반환

하겠죠…. 만약에 man.prototype 에서 조차도 없다. 그럴땐 더 상위로 가봅니다..

즉 Object.prototype 에서 찾아 보는겁니다.  이마저 없을땐 오류가 발생하는거죠…

그림으로 볼까요? (필요 없을려나 -_-;;;)

사용자 삽입 이미지

자 관련 소스를 하나 볼까요 ^^;;

   

  1. var man = function(name){  
  2.     this.name = name;  
  3.     this.getName = function(){  
  4.         alert(‘man:’ + this.getName);  
  5.     }  
  6. }  
  7.   
  8. man.prototype.getName = function(){  
  9.         alert(‘man.prototype:’+this.name);                    
  10. }  
  11.   
  12.   
  13. Object.prototype.getName = function(){  
  14.         alert(‘Object.prototype:’+this.name);                     
  15. }                 
  16.   
  17. var niceguy = new man(“멋진인생”);  
  18. niceguy.getName();  

역시 예상대로 man 의 getName 을 가져오는군요….

이렇듯 prototype 베이스 상속이란건 실제로 값을 가져다가 복사하는게 아닌

상위로 찾아가면서 값을 구하는 거예요..

그럼 prototype 에서의 읽기는 그렇다 치고 쓰기는 어떨까요??

   

  1. var man = function(name){  
  2.     this.name = name;  
  3. }  
  4.   
  5. man.prototype.age = ’13’  
  6.   
  7. var niceguy = new man(‘멋진인생’);  
  8.   
  9. alert(niceguy.age) // 13 반환  
  10. alert(niceguy.hasOwnProperty(“age”)); // false 반환  
  11. niceguy.age = ’14’;  
  12. alert(niceguy.age)   // 14 반환         
  13. alert(niceguy.hasOwnProperty(“age”)); // true 반환      

age 프로퍼티를 하나 추가하려 합니다.. 보통 man 자체에 넣겠지만 prototype 에 넣어 보도록

하죠… 그럼 최초에 niceguy.age 호출시 man 에 있는지 확인 합니다.. 물론 없습니다.

그럼 man.prototype 에서 찾아 봅니다.. 자 있습니다.. 13을 반환 합니다.

niceguy.hasOwnProperty 를 호출 합니다. hasOwnProperty 메소드는 해당 객체 자체에 있는

프로퍼티 일 경우는 true , prototype 등으로 상속 받은 경우는 false 를 반환 합니다..

당연히 man.prototype 에서 가져온 age 이기 떄문에 false 를 반환 합니다.

그 뒤에 niceguy.age 의 값을 변경해 봅니다..

이때 주의하셔야 할것이 man.prototype 의 age 의 값을 변경하지 않는다는 겁니다..

man 자체에 age 란 변수를 만들고 그뒤에 14 값을 넣습니다..

이제 niceguy.hasOwnProperty 를 호출하면 true 를 반환 하는것을 알수 있습니다..

사실 prototype을 사용하실때 주의 하셔야 할점도 있습니다.

prototype.js 를 보신분들은 알고 계시겠지만 내장 타입도 확장을 함으로써 편하게 사용하실수

있게 만들어 놨습니다.

   

  1. Array.prototype.clear = function(){  
  2.         this.length = 0;  
  3. }  
  4.   
  5. var arr = [1, 2, 3];  
  6.   
  7. alert(arr); //[1, 2, 3]  
  8.   
  9. arr.clear()  
  10.   
  11. alert(arr); // []   

예제 소스가 한없이 저렴하네요 -_-;;;

상기 소스 처럼 내장 타입도 확장할수 있지만 Object.prototype 만은 테스트 용도가 아닌경우

확장 하길 권하지 않습니다… 왜 그런지는 충분히 아실거라 생각합니다……

사실 prototype 은 저정도 이외에도 내부적으론 좀더 복잡하게

돌아가는거 같습니다만 ….. 그건 좀더 확인해 본뒤에 글을 적도록 하죠~

업무시간에 적느라 눈치가 보이네요 -_-;;;;;

긴글 읽느라 고생하셨습니다…

Comments are closed.

Post Navigation