자바스크립트에서 this에 대해 공부하다 보면 이해한거 같다가도 클로저 함수가 들어오면 또 이해가 안되는 경우가 많아


this에 대한 이해를 IIFE 패턴에서 어떻게 사용되는지 확인해 보았습니다.


this는 함수 함수 scope 단위로 생성 됩니다. 라는 점을 알고 작성하겠습니다.


해당 객체를 통해서 this의 생성 범위를 확인 해 보면


iife = (function (){

var a = function(){

console.log('iife function a ', this);

                }

       return {

a:a,

       }

})();



결과 :


iife.a();

iife function a  {a: ƒ}


이제 함수 몇개를 추가하여서 iife라는 객체에서 return 되지 않는 함수에 대한 this 확인 

-> 이점이 처음에 this와 iife에 대해서 잘못 이해 하였던 부분이 있습니다.


c계열에서 class라고 생각하다 보면  iife라는 객체로 감싸져있기 때문에 어떤 함수여도 this는 iife라고 생각 했기 때문입니다.



iife = (function (){

		var outerFunction_aa = function(){

		console.log('iife function a ', this);
			
				// this.inner_d(); // error is not a function
				// this.inner_e(); // error is not a function

				inner_d();   // success    -> inner delcaration function  [ window ]
				inner_e();   // success    -> inner expression function  [ window ]
        }


  		// function declaration
		function inner_d(){
				console.log('inner declaration function', this);
        }
		// function expression
		var inner_e = function (){
				console.log('inner expression function',this);
        }

		var outerFunction_b = function(){
				console.log('outer expression function_b ' , this);
        }



       return {
		outer_a : outerFunction_a,
		outer_b : outerFunction_b,
       }

})();

결과 : 실행은 iife.outer_a(); 로 하였을때

this.inner_d();  

this.inner_e();  두 함수다 에러로 표시되며 메시지는 is not a function 

즉 this에 inner_d 가 없다는 뜻입니다. 

(js에서 inner_d가 프로퍼티인데 지정이 안되었을 경우는 undefined 로 되기 때문에 호출하여도 에러는 나지 않습니다.)

하지만 함수의 경우는 실행을 하여야 하기 때문에 정의되거나 함수이지 않은 경우는 is not a function 에러가 나타나게 됩니다.


하지만 this를 제외하고 실행시 

inner_d();  

inner_e();  두개의 함수다 실행되며 내부 함수에서 this는 [window] 가 잡힙니다.


??? IIFE 패턴으로 묶었는데 왜 window가 잡히는지 이해가 잘 안됩니다. 


-> 사실은 이게 class처럼 감싸진게 아닙니다. 


iife객체는 생명주기가 끝난  익명함수의 실행컨텍스트를 가지고 있습니다.


iife객체는 현재 return 되었던 outer_a 와 outer_b 만 을 가지고있습니다.


일반 함수에서 this는 [window]인것 처럼


IIFE패턴과 같이 위에 처럼 작성되어도 

return  { 

// closure space 

}


가 포함되어있지 않은 함수는 expression(함수 표현식) 이나 declaration(선언식) 이나 window를 지칭하게 됩니다. 


하지만 함수 자체(return 되지않은 inner_d)는 


iife.a() 형태로 직접 실행되지 않았기 때문에 this는 [window] 에 바인딩되게 된다.


this의 생성 조건은  해당 메서드를 호출한 객체로 바인딩 이기 때문이다.


그렇기 때문에


iife.outer_a(); 로 호출하였을 경우 outer_a()는 앞에 iife객체가 this가 되지만 해당 함수 내부에서 내부 함수를 호출하기 위해서는


inner_d();   // success    -> inner delcaration function  [ window ]
inner_e();   // success    -> inner expression function  [ window ]

해당형식으로만 선언할수 있기 때문이다.  해당 함수의 선언이 가능한 이유는 iife의 실행컨텍스트 안에 들어있기 때문에 그냥 선언해서


사용하여야 한다.  this로 안나오는 경우는 this가 window이기 때문이다.  


그러면 private하게 변수나 함수를 어떻게 사용하여야 할까


함수 선언식과 표현식은 호이스팅의 차이 유무가 있기 때문에 이후 코드는 표현식으로 사용하겠습니다.


정말 처음에 공부할때 바로 생각도없이 아 그러면 return 함수를 만들고 그안에서 this . value로 쓰면되겠다!


그러면 private로 쓸수 있을줄 알았다면



iife = (function (){
	var innerValue = 1;
		var outerFunction_a = function(){
			console.warn(this);
			console.warn('inner Value ', this.innerValue);	
		}

		var outerFunction_b = function(){
			console.warn('inner Value ', this.innerValue);				
        }

	// function expression
		var inner_e = function (){
			console.warn(innerValue);
        }



       return {
		outer_a : outerFunction_a,
		outer_b : outerFunction_b,
       }

})();

결과 : 실행은 iife.outer_a(); 로 하였을때

▶ : {outer_a:f, outer_b:f}

▶ : inner Value undefined 

undefined로 나온다. 왜 return 을 안했기 때문


innerValue :innerValue, 로 리턴을 해주면 동작은 하지만 그렇게 되면 private 라고 할수 있을까


iife.innerValue = 5 를 입력하게되면 내부값 역시 5로 바뀌기 때문이다. 


일단 내부 변수를 밖으로 빼내는거 자체가 좋은생각은 아니기 때문에 getter, 와 setter를 활용 한다.


또한 내부 함수를 스코핑을 통해서 실행시키기 위해서는


var this_ = this; 를 활용한다.


이에 대한 기본적인 구성은


iiife = (function (){
	var innerValue = 1;
	var arr= [0];
		var outerFunction_a = function(){
			console.warn(this);
			console.warn('inner Value ', innerValue);	
		}

		var thisChange = function(){
				console.warn('thisChange tihs');
				console.log(this);
				var _this = this;
				
				console.warn('forEach this');
					arr.forEach(function(item,index){
								console.log(this);
								console.log(_this);
                    });
				console.warn('map this');
					arr.map(function(item){
							console.log(this);
							console.log(_this);
                    });
			
				console.warn('arrow function this');
			
					arr.map( item => {
							console.log(this);
							console.log(_this);
                    });


					
        }

	// function expression
		var inner_e = function (){
			console.warn(innerValue);
        }

		var getValue = function(){
				this.innerValue;
        };
		
		var setValue = function(value){
				this.innerValue = value;
        };

       return {
		outer_a : outerFunction_a,
		thisUse : thisChange,
		setValue : setValue,
		getValue : getValue,
       }

})();
iife.thisUse();


arrow function 을 쓸 경우는 새로운  this가 바인딩되지 않습니다. 이것은 arrow function 에서 새롭게 포스팅 하도록 하겠습니다.


위의 코드 결과입니다.




getter,setter에 대한 포스팅은 


http://benalman.com/news/2010/11/immediately-invoked-function-expression/#iife 에 자세하게 잘 나와있어 링크 합니다.




+ Recent posts