2015년 6월 16일 화요일

javascript prototype

javascript prototype 에 대한 고찰

        Selector.index = 0;
 Selector.prototype.getIndex = function(){  
  return this.constructor.index++;
 };
 function Selector(){
  this.index = this.getIndex();
  
  alert(this.constructor.index);
  
  this.print = function(){
   alert(this.index);
  };
 }
 
 var a1 = new Selector();





나는 여러개의 Selector 생성시 내부적으로 셀렉터의 ID를 관리하고 싶었다. 그래서 위 처럼 this.constructor.index++ 을 사용했는데..
이처럼 해도 되는거는.. this의 constructor 는 function Selector 일거고 Selector 라는 함수원형에 index가 추가 선언되어 있으니 
접근가능한것이라고 이해했음. 그냥 Selector.index++ 로 해도 된다.

prototype에 대해서.. 
함수원형을 만들때 원형 자체는 객체가 아니다. 객체를 확장시킬시에 사용되는 틀에 불과하며 게다가 내부적으로 이미 prototype 즉
객체를 확장시키기 위한 객체가 만들어져 링크되어있다. 이것이 바로 prototype 이다. 

그러므로 Selector.prototype.getIndex 을 선언했을때 new 키워드를 사용해서 객체를 생성하면 Selector 의 prototype 객체를 사용해서 
만들어지므로 getIndex가 확장된다. 그리고 new 당시 생성자 즉 Selector() 에서 정의된 내용은 prototype의 constructor 에 링크되어있다. 
즉 서로 맞물려있는 관계라고 볼수있따. 

2014년 7월 22일 화요일

javascript Closure


	(function(){
		var j=0;
		for(var i=0;i<10;i++){
			++j;
			(function(){
				var idx = j;
				$("",{
							text:idx,
							style:"padding:2px;",
							click:function(){
									alert(idx);
								}					
				}).appendTo($("#closureTest"));			
			})();
		}		
	})();




javascript 의 모든 함수는 Closure 이다. 

최소한 내가 이해하고 있는 Closure 란 함수가 호출될 당시에 접근 할 수 있는 코드블럭이다.

위의 코드를 약간 수정해 보면


        (function(){
		var j=0;
		for(var i=0;i<10;i++){
			++j;
			
				var idx = j;
				$("",{
							text:idx,
							style:"padding:2px;",
							click:function(){
									alert(idx);
								}					
				}).appendTo($("#closureTest"));			
			
		}		
	})();


익명 함수를 제거해보았다.

언뜻 보면 의도대로 동작할 거 같지만 

click 이벤트가 발생되서 함수가 호출될 시점과 선언된 시점의 idx 값이 다르게 된다.

즉, 함수가 사용하는 변수는 내부적으로 계속 참조하고 있다는 말이 된다.

이는 전역변수를 생각해보면 이해가 될것이다.

그래서 익명함수를 사용하여 스코프를 분리하고 참조블럭을 변경시켜주는 작업을 통해 해결 할 수 있다.

2014년 6월 10일 화요일

jQuery.proxy


function Obj(){
	
	this.init = function(text){
		this.text = text;	
		
		var span = $("",{
						text:this.text,
						click:$.proxy(this, 'clickHandler')
					});
		
		$("#proxyTest").append(span);
	};
	
	this.clickHandler = function(){
		alert(this.text);
	};
}


$(function(){
	
	var Obj_1 = new Obj();
	Obj_1.init("프록시테스트1");
	
	var Obj_2 = new Obj();
	Obj_2.init("프록시테스트2");
});

id가 proxyTest 인 엘리먼트를 두고 위와 같은 코드를 작성할시 
프록시테스트1프록시테스트2 라고 화면에 나타난다.

위 코드의 목적은 프록시 설명을 위한거인데 프록시는 대리자, 대리인의 뜻을 가지고있다. 
뭐 뜻이 중요한건 아니고 아무튼 $.proxy 의 역할을 설명하자면
this 를 이용해 현재 context 의 'clickHandler' 속성을 확장한다는 뜻이다.

무슨 뜻이냐하면
만약에 
function Obj(){
	
	this.init = function(text){
		this.text = text;	
		
		var span = $("",{
						text:this.text,
						click:this.clickHandler
					});
		
		$("#proxyTest").append(span);
	};
	
	this.clickHandler = function(){
		alert(this.text);
	};
}
위와 같이 작성할때 아무런 문제가 없어보인다. 하지만 실제로 클릭을 해보면
아무런 반응이 없거나 스크립트 오류가 날 것이다. 그 이유는 이벤트 발생시에 
this에 해당하는 객체가 재정의되기 때문이다.
실제로 this를 찍어보면 jQuery234234234 이런 값이 있는 것을 확인 할 수 있다.
그래서 $.proxy 메소드를 이용하여 원래의 this를 이용해서 확장시켜주는 것이다.

요약:span의 click 이벤트핸들러가 실행되는 시점의 컨텍스트 즉, 실행주체가 변경되기 때문에
this 키워드가 가리키는 객체가 달라지는 것이다.