자바스크립트 - this

pa324·2019년 11월 24일
0

상황에 따라 달라지는 this

  • this는 실행 컨텍스트가 생성될 때 함께 결정
  • 실행 컨텍스트는 함수를 호출할 때 생성되므로, this는 함수를 호출할 때 결정된다.

전역 공간 this

  • 전역 공간에서 this는 전역 객체를 가리킨다.
  • 전역 컨텍스트를 생성하는 주체가 전역객체
  • Browser는 window객체, Node환경은 global객체
  • 전역 변수를 선언하면, 자바스크립트 엔진은 전역객체의 프로퍼티로도 할당시킨다.
    • 자바스크립트의 모든 변수는 특정 객체의 프로퍼티로 동작한다.
      • 사용자가 var연산자를 이용해 변수를 선언하더라도 실제 자바스크립트 엔진은 어떤 특정 객체의 프로퍼티로 인식한다.
        • 특정 객체는 실행 컨텍스트의 Lexical Environment이다.
          • 실행 컨텍스트는 변수를 수집해서 Lexical Environment의 프로퍼티로 저장한다. 그리고 어떤 변수를 호출하면 Lexical Environment를 조회해서 일치하는 프로퍼티가 있을 경우 그 값을 반환(전역 컨텍스트의 Lexical Environment는 전역 객체를 그대로 참조한다.
var a = 1;
console.log(a); // 1
console.log(window.a) // 1
console.log(this.a) // 1

메서드로서 호출 할때 그 메서드 내부에서의 this

함수 vs 메서드

  • 함수는 그 자체적으로 독립적인 기능을 수행한다.
  • 메서드는 자신을 호출한 대상 객체에 관한 동작을 수행한다.

메서드 내부에서의 this

  • this에는 호출한 주체에 대한 정보가 담긴다.
  • 메서드로서 호출하는 경우 호출 주체는 바로 함수명 앞의 객체가 된다.
var obj = {
  methodA : function () {console.log(this)} // obj출력
}
obj.methodA()

함수 내부에서의 this

  • 어떤 함수를 함수로서 호출할 경우에는 this가 지정되지 않는다. 실행 컨텍스트를 활성화할 당시에 this가 지정되지 않은 경우 this는 전역 객체를 바라본다.
    • 자바스크립트 설계상의 오류로 알려짐
    • 아래 예제에서 (2),(3)은 같은 함수임에도 바인딩되는 this가 서로 다르다.
      • this바인딩이 함수를 실행하는 당시의 주변환경은 중요하지 않고, 오직 해당 함수를 호출하는 구문 앞에 점 또는 대괄호 표기가 있느지 없는지가 관건
var obj1 = {
  
  outer : function() {
  	console.log(this); // (1) -> obj1 출력
    var innerFunc = function() {
    	
      console.log(this);//(2)(3) -> 전역출력,obj2출력
    
    }
    innerFunc()
    
    var obj2 = {
      innerMethod : innerFunc
    };
    obj2.innerMethod();
  }
  

this우회하는 방법


var obj1 = {
  
  outer : function() {
  	console.log(this); // (1) -> obj1 출력
    var innerFunc = function() {
    	
      console.log(this);//(2)(3) -> 전역출력,obj2출력
    
    }
    innerFunc()
    
    var self = this;
    var obj2 = function () {
    	console.log(self);// obj1을 가르킨다.
    }
    obj2();
 }
 obj1.outer();
  

arrow function

  • ES6에서는 함수 내부에서 this가 전역객체를 바라보는 문제를 보완하고자, this를 바인딩하지 않는 arrow function을 새로 도입.
  • 실행 컨텍스트를 생성할 때 this 바인딩 과정 자체가 빠지게 되어, 상위 스코프의 this를 그대로 활용할 수 있다.

명시적 this 바인딩

call 메서드

  • call 메서드는 호출 주체인 함수를 즉시 실행하도록 하는 명령이다.
  • call메서드의 첫번째 인자를 this로 바인딩하고, 이후의 인자들을 호출할 함수의 매개변수로 사용
  • call을 통해서 함수를 호출하면 임의의 객체를 this로 바인딩 가능하다.
  • Function.prototype.call(thisArg[,arg1[,arg2[,...]]])

var func = function (a,b,c) {
  console.log(this,a,b,c);
}

func(1,2,3) //window,1,2,3
func.call({x:1},4,5,6) // {x:1} 4 5 6
var obj = {
	a : 1,
    method : functionb(x,y) {
		console.log(this.a,x,y);
	}
}
obj.method(2,3)//  1 2 3
obj.method.call({a:4},5,6) // 4 5 6

apply 메서드

  • call과 기능적으로 완전히 동일
  • apply메서드는 두 번째 인자를 배열로 받아 그 배열의 요소들을 호출할 함수의 매개변수로 지정한다 (call과의 차이)
var obj = {
	a : 1,
    method : functionb(x,y) {
		console.log(this.a,x,y);
	}
}
obj.method(2,3)//  1 2 3
obj.method.apply({a:4},[5,6]) // 4 5 6

call / apply 활용

  • 유사배열객체에 배열 메서드를 적용
  • 객체에 배열 메서드를 적용할 수 없지만, 키가 0 또는 양의 정수인 프로퍼티가 존재하고 length 프로퍼티 값이 0또는 양의 정수인 객체는, call / apply를 이용해 배열 메서드를 차용할 수 있다.

var obj = {
	0 : 'a',
  	1 : 'b',
    2 : 'c',
  	length : 3
}

Array.prototype.push.call(obj,'d');
console.log(obj) // d가 obj에 추가됨

var arr = Array.prototype.slice.call(obj);
console.log(arr) // ['a','b','c','d']

ES6 Array.from


var obj = {
	0 : 'a',
  	1 : 'b',
    2 : 'c'
}
var arr = Array.from(obj);
console.log(arr) // ['a','b','c']

bind method

  • es5에서 추가된 기능으로 call과 비슷하지만 즉시 호출하지 않고 넘겨받은 this및 인수들을 바탕으로 새로운 함수를 반환하기만 하는 메서드이다.
profile
안녕하세요

0개의 댓글