programming language/javascript

This란?

공대키메라 2021. 9. 1. 20:52

전에 Context에 대해 공부해보았다.

 

다시 보고 싶다면 링크를 달아두겟다옹 히힛

 

https://tech-monster.tistory.com/41

 

Context 란?

내가 공부하고자 하는 전반적인 내용이 아래 블로그에 담겨있다. https://poiemaweb.com/js-execution-context Execution Context | PoiemaWeb Execution Context(실행 컨텍스트)는 scope, hoisting, this, functi..

tech-monster.tistory.com

 

 

여기 inner안에 보면 ThisBinding이라는 아이가 있다. 이건 뭥미?

 

우선 제대로 알기 전에 이 문장을 기억하란다

 


thisBinding은 실행 컨텐스트가 활성화될 때 한다!

 

실행 컨텍스트가 생성될 때 this를 binding한다고 한다

 

근데 실행 컨텍스트는 언제 생성되나? 바로 컨텍스트에 해당하는 함수가 호출되는 순간이다!

 

this가 함수가 호출될 때 비로소 결정되는 것이다!

 

그러니까 this는, 정적으로 코드만 봣을 때 바로 예측할 수 있는게 아니라 함수를 어떤식으로 호출했느냐에 따라 this는 동적으로 바인딩이 가능하다는 말이다!

 

구체적으로 어떻게 다른지를 그러면 알아보도록 하자

 

호출하는 방식은 크게 5가지로 나눌 수가 있다고 한다. 

많기도하네 참...

참고 해보자 ^^ 너무재미잇엉 ㅎㅎ 

 

1. 전역공간에서의 this

여기서 this는 전역 객체를 가리킨다.

브라우저에서는 window, node.js에서는 global이라는 객체를 가리킨다. 

 

개념상 전역 컨텍스를 실행하는 주체가 바로 전역객체이기 때문이다. 

 

자바스크립스가 실행되는 환경, 즉 런타임에 따라서 전역객체의 정보가 달라진다. 

 

chrome 에서 f12를 눌러서 this를 출력하면 다음과 같이 나온다.

 

 

궁금하면 한번 쳐봐!

 

각 호스트 환경에서  정의한 바에 따라서 전역객체의 구체적인 내용이 달라진다.

 

그래서 결론 => 전역 공간에서 this는 전역 객체를 가리킨다!

 

2. 함수 호출시

여기서  this는 함수를 호출했을 때도 전역 객체를 가리킨다. 오잉?

 

function b(){
	function c(){
    		console.log(this);
    }
    c();
}
b();

 

우리가 여기에서 일반적으로 생각하면 b()를 호출하면서 c()가 함께 호출되니 b가 this아닌가 싶은데

어림없는 소리! 그렇지 않다고 한단다. 

 

javascript가 애초에 1주일만에 급하게 만들어진 언어라 이것을 버그라 봐야할지는 의견이 분분하다고 한다. 

 

그래서 ECMAScript6에서는 이것이 문제라는 의견을 수렴해서 아예 this 바인딩을 하지 않는 arrow function이란게 나왔다고 한다. 

 

하지만 ES5환경에서는 무적권 this는 언제나 전역 객체를 가리킨다. 


다시 하나를 예로 들어보자. 

var d = {
 e : function(){
  function f(){
   console.log(this);
  }
  f();
 }
}
d.e();

객체 안에 e라는 메소드가 있고 맨 밑에서 메소드로 호출하고 있다. 

 

근데 f()를 그 안에서 다시 호출하네? => 함수에서는 무조건 전역 객체!

 

3. 메소드 호출 시

메소드를 호출한 주체가 this이다.

 

var a = {
   b : function(){
      console.log(this);
   }
}
a.b();

이렇게 부르면 a가 this가 된다. 

앞에 "."이 있으면 그 앞의 객체의 메소드로서 이 b를 호출했다는 뜻이 된다. 

 

그러면 다음은?

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

 

this는 a.b가 된다. 

 

주의할 점은 "." 말고소 대괄호로도 접근이 가능하다는 것이다 

 

obj.func(); => obj['func']();

person.info.getName(); => person.info['getName']();

 

근데 함수에서는 this를 호출하면 무조건 전역 객체를 본다고 햇는데 

 

이것을 다르게 우회하는 방법도 있다. 

 

우선 밑에는 그냥 우회하지 않고 한거다. 

var a = 10;
var obj = {
  a: 20,
  b: function(){
    console.log(this.a); // <= obj를 가리킴 20 출력
    function c(){
      console.log(this.a); // <= 전역 객체를 가리킴 10 출력
    }
    c();
  }
}
obj.b();

다음은 좀 다르게!

var a = 10;
var obj = {
  a: 20,
  b: function(){
    var self = this;
    console.log(this.a); // 20 
    
    function c(){
      console.log(self.a); // 20
    }
    c();
  }
}
obj.b();

ES6에서는 this를 바인딩 하지 않은 arrow function이라는게 등장하면서 이런 우회법을 쓸 필요가 사실상 없어졌다.

 

var a = 10;
var obj = {
  a: 20,
  b: function(){
    console.log(this.a); // 20 
    
    const c = () => { // arrow function의 this는 this를 바인딩 하지 않아 상위에 바로 접근
    	console.log(this.a); // 20
    }
    c();
  }
}
obj.b();

ES5 에서 위와 같이 하는 방법도 있다. 

// call & apply 적용
var a = 10;
var obj = {
  a: 20,
  b: function(){
    console.log(this.a); // 20 
    
    function c(){
      console.log(this.a); // 20
    }
    c.call(this);
  }
}
obj.b();

 

4. callback 호출시

=> 기본적으로 함수내부에서와 동일!

 

이게 무슨 소리냐?

 

우선 callback 내에서의 this에 대해 논하기 전에 call, apply, bind메소드에 대해 배경지식을 알아야 한단다!

 

예시 코드를 보자.

 

function a(x,y,z){
	console.log(this, x, y, z);
}

var b = {
	bb: 'bbb'
};

a.call(b, 1, 2, 3); // this가 b를 가리킴

a.apply(b, [1, 2, 3]);

var c = a.bind(b); //아직 함수 호출 안함. this를 a로 넘겨줌
c(1, 2, 3)

var d = a.bind(b, 1, 2); // 우선 this 랑 매개변수  1, 2를 넘김
d(3); // 마지막 변수 3을 넘김으로 완성

위 예제들은 출력하면 모두 같은 것을 출력한다. 

 

요로콤~!

 

api문서들을 살펴보면 이렇단다. 대괄호는 생략이 가능하다는 말이다. 

 

thisArg라고 하는 부분에 this를 넣어줘! 하는 것으로 이것들을 명시적인 this 바인딩이라고 한다. 

 

다른 예를 들어 그러면 또다시 this를 알아보자. 

 

 //-------------------1----------------
 var callback = function(){
 	console.dir(this);
 };
 
 var obj = {
 	a: 1,
    b: function(cb){
    	cb();
    }
 };
 
obj.b(callback); 

// 메소드로서 호출!
//cb에 변수 callback에 선언된 함수가 들어감.
//cb()에서 넘어온 함수가 실행됨 
//cb()는 console.dir(this)를 실행시킴
// 함수에서 this를 호출했으니 this 는 전역객체!
//
//-------------------2----------------
var callback = function(){
	console.dir(this);
};

var obj = {
	a: 1,
    b: function(cb){
    	cb.call(this);
    }
};
obj.b(callback);

//obj.b(callback)에서 obj객체의 b 메소드에 변수로 선언된 함수 callback 전달
//thisArg에 this를 넘김
//this를 call로 부름 => obj가 this가 됌

다른 예제를 보자.

var callback = function(){
	console.dir(this);
};

var obj = {
	a: 1
};

setTimeout(callback, 100); // 전역객체 출력
setTimeout(callback.bind(obj), 100); // obj 출력

 

다시~

document.body.innerHTML += '<div id="a">클릭하세요</div>';

document.getElementById('a').addEventListener(
	'click',
    function(){
    	console.dir(this);
    }
);

// addEventListener라는 함수가 콜백함수를 처리할 때
// this는 이벤트가 발생한 그 타겟 대상 엘리먼트로
// 하도록 정의가 되 있음

 

정리해보면 콜백함수는?

 

  1. 기본적으로는 함수의 this와 같다. 
  2. 제어권을 가진 함수가 콜백의 this를 지정해둔 경우도 있다. 
  3. 이 경우에도 개발자가 this를 바인딩해서 콜백을 넘기면 그에 따른다.  

 

(아직 안끝낫다 ㅎㅎ... 너무 길어 ㅠㅠ )

5. 생성자 함수 호출시

=> new를 썻다는 말은 생성자 함수를 바탕으로  인스턴스 객체를 만드는 명령

 

이때는 새로 만들 인스턴스 객체 그 자체가 곧 this가 된다. 

 

//-------------------------1--------------------------
function Person(n, a){
	this.name = n;
    this.age = a;
}

var roy = Person('재남', 30);
console.log(window.name, window.age);

// new 없이 Person을 호출하면 roy에는 아무것도 담기지 않는다.
// 결국 함수로서 호출한 것이기 때문에 이때의 this는 전역객체를 가리킨다. 
// 그러면 전역 객체의 name property와 age property에 값이 할당 되어서 
// 재남 30이 출력된다. 
//-------------------------2--------------------------
function Person(n, a){
	this.name = n;
    this.age = a;
}

var roy = new Person('재남', 30);
console.log(roy);

// 새로 생성될 person의 인스턴스 객체 자신이 곧 this가 됨. 
// 객체가 새로 만들어지면서 그 객체 안에 name 프로퍼티, age 프로터디가 생성되면서 
// Person객체를 부르는것을 확인할 수 있다.

 

'programming language > javascript' 카테고리의 다른 글

Prototype이란?  (4) 2021.09.02
Closure란?  (0) 2021.09.01
Callback Fucntion 이란?  (0) 2021.09.01
Context 란?  (2) 2021.08.31
Primitive Type vs Reference Type  (5) 2021.08.29