관리 메뉴

공부기록용

JavaScript 문법 종합 3주차 (실행컨텍스트_this) 본문

📚강의록📚/스파르타)Javascript

JavaScript 문법 종합 3주차 (실행컨텍스트_this)

과부하가즈아 2023. 6. 13. 21:40
실행 컨텍스트는 실행할 코드에 제공할 환경 정보들을 모아놓은 객체
✓ VariableEnvironment
✓ LexicalEnvironment
✓ ThisBindings

this

다른 객체지향 언어에서의 this는 곧 클래스로 생성한 인스턴스를 말한다. 그러나 자바스크립트에서는 this가 어디에서나 사용될 수 있다.

 

상황에 따라 달라지는 this

this는 실행 컨텍스트가 생성될 때 결정(bind)된다. 

 

전역 공간에서의 this

런타임 환경 : 코드가 돌아가는 환경(javascript로 만들어놓은 프로그램이 구동중인 환경)
전역 환경에서  this는 노드에서는 global 객체이고, 브라우저에서는 window 객체이다.

-> 노드 환경 : node 파일이름.js로 vscode 상에서 구동하고 있으니node 환경

노드환경에서 this라는 전역 변수는 글로벌이다.



-> 브라우저 환경 : html 파일 안에 숨겨놓아서 크롬브라우저 등에서 연다고 한다면 브라우저 환경

>> 브라우저 환경에서 확인해보면 window라고 보인다(브라우저 환경을 의미)


함수 vs 메서드

기준은 독립성, 함수는 그 자체로 독립적인 기능을 수행하고, 메서드는 자신을 호출한 대상 객체에 대한 동작을 수행한다.
// 함수
함수명();

// 메서드
객체.메서드명();

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


함수
에서의 this의 경우 함수는 호출 주체를 명시할 수 없기 때문에 this는 전역 객체를 의미한다.

// 함수
// 브라우저라는 환경이라는 조건하에
var func = function (x) {
	console.log(this, x);
};
func(1); // Window { ... } 1
// func(1)로 앞에 별다른 호출의 주체가 없는 단순 함수이므로
// 이 함수안에서의 this는 항상 window 객체일 수 밖에 없다.(전역객체)

메서드경우 호출 주체를 명시할 수 있기 때문에 this가 호출의 주체가 된다.(해당 객체를 의미한다.)

var func = function (x) {
	console.log(this, x);
};
func(1); // Window { ... } 1

// 메서드
var obj = {
	method: func,
};
obj.method(2); // { method: f } 2
// 호출 객체를 명시했기 때문에(obj.함수를 실행하면서 메서드를 호출)

함수로서의 호출과 메서드로서의 호출 구분 기준 :  .  /  [ ]


메서드 내부에서의 this_this에는 호출을 누가 했는지에 대한 정보가 담긴다.

var obj = {
	methodA: function () { console.log(this) },
	inner: {
		methodB: function() { console.log(this) },
	}
};

obj.methodA();             // this === obj
obj['methodA']();          // this === obj

obj.inner.methodB();       // this === obj.inner
obj.inner['methodB']();    // this === obj.inner
obj['inner'].methodB();    // this === obj.inner
obj['inner']['methodB'](); // this === obj.inner

함수로서 호출할 때 그 함수 내부에서의 this

어떤 함수를 함수로서 호출할 경우, this는 지정되지 않아요(호출 주체가 알 수 없으므로)
실행컨텍스트를 활성화할 당시 this가 지정되지 않은 경우를 의미하며, this는 전역 객체를 의미한다.
함수로서‘독립적으로’ 호출할 때는this는 항상 전역객체를 가리킨다


메서드의 내부함수에서의 this
메서드의 내부라고 해도, 함수로서 호출한다면 this는 전역 객체를 의미한다.
var obj1 = {
    outer: function () {
        console.log(this); // (1) obj1.outer() 실행 
        var innerFunc = function () {
            console.log(this); // (2) innerFunc 실행, (3) obj1.outer() -> innerFunc 실행 
        }
        innerFunc();

        var obj2 = {
            innerMethod: innerFunc
        };
        obj2.innerMethod();
    }
};
obj1.outer();​

메서드의 내부 함수에서의 this 우회

변수를 활용하는 방법
내부 스코프에 이미 존재하는 this를 별도의 변수(ex : self)에 할당하는 방법

var obj1 = {
	outer: function() {
		console.log(this); // (1) outer

		// AS-IS : 기존의 것
		var innerFunc1 = function() {
			console.log(this); // (2) 전역객체
		}
		innerFunc1();

		// TO-BE : 이후의 것
		var self = this;
		var innerFunc2 = function() {
			console.log(self); // (3) outer
		};
		innerFunc2();
	}
};

// 메서드 호출 부분
obj1.outer();​

화살표 함수(=this를 바인딩하지 않는 함수)

화살표 함수는, 실행 컨텍스트를 생성할 때 this 바인딩 과정 자체가 없다. 따라서 this는 이전의 값-상위값-이 유지되는데, ES6에서는 함수 내부에서 this가 전역객체를 바라보는 문제(this의 유실) 때문에 화살표함수를 도입되었다.

일반 함수와 화살표 함수의 가장 큰 차이점 : this binding 여부
var obj = {
	outer: function() {
		console.log(this); // (1) obj
		var innerFunc = () => {
			console.log(this); // (2) obj
		};
		innerFunc();
	}
}

obj.outer();

콜백 함수 호출 시 그 함수 내부에서의 this

콜백 함수도 함수이므로 함수로써 this를 잃어버리게 된다. (thisBinding을 하면 다 전역객체를 바라보게 됨)

// 별도 지정 없음 : 전역객체
setTimeout(function () { console.log(this) }, 300);

// 별도 지정 없음 : 전역객체
[1, 2, 3, 4, 5].forEach(function(x) {
	console.log(this, x);
});

// addEventListener를 호출한 주체를 바라보게 끔 되어있음
// addListener 안에서의 this는 항상 호출한 주체의 element를 return하도록 설계되었음
// 따라서 this는 button을 의미함
document.body.innerHTML += '<button id="a">클릭</button>';
document.body.querySelector('#a').addEventListener('click', function(e) {
	console.log(this, e);
});
  1. setTimeout 함수, forEach 메서드는 콜백 함수를 호출할 때 대상이 될 this를 지정하지 않으므로, this는 곧 window객체
  2. addEventListner 메서드는 콜백 함수 호출 시, 자신의 this를 상속하므로, this는 addEventListner의 앞부분(button 태그)_예외적인 상황에 속함(콜백 함수에 별도로 this를 지정한 경우)

생성자 함수 내부에서의 this

var Cat = function (name, age) {
	this.bark = '야옹';
	this.name = name;
	this.age = age;
};

var choco = new Cat('초코', 7); //this : choco
var nabi = new Cat('나비', 5);  //this : nabi

 

 

Comments