this 바인딩

Jtiiin:K·2023년 10월 16일
0
post-thumbnail

This

this는 실행 컨텍스트가 생성될 때 결정됨 = this를 bind한다(=묶는다)
=> this는 함수를 호출할 때 결정된다


✅ 전역 공간에서의 this

  • 전역 공간에서 this는 전역객체
  • 런타임 환경에 따라 this는 window(브라우저 환경) 또는 global(node 환경)를 각각 가리킴
    📝 런타임 환경이란?
    javascript로 만들어놓은 프로그램이 구동중인 환경

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

✔ 함수 vs 메서드

  • 함수와 메서드는 비슷해 보이지만 독립성을 기준으로 차이가 나뉨
  • 함수는 그 자체로 독립적인 기능을 수행
// 함수
함수명()
// 메서드 
객체.메서드명()

✔ this의 할당

// 함수
// 호출 주체를 명시할 수 없기 때문에 this는 전역 객체
var func = function (x) {
	console.log(this, x);
};
func(1); // Window { ... } 1

// 메서드
// 호출 주체를 명시할 수 있기 때문에 this는 해당 객체(obj)를 의미
// obj는 곧 { method: f }를 의미하죠?
var obj = {
	method: func,
};
obj.method(2); // { method: f } 2

✔ 함수로서의 호출과 메서드로서의 호출 구분 기준

  • . or []
var obj = {
	method: function (x) { console.log(this, x) }
};
obj.method(1); // { method: f } 1
obj['method'](2); // { method: f } 2

✔ 메서드 내부에서의 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는 전역객체 (예외 없음)
  • 💡 함수를 실행할 당시 주변환경(메서드 내부인지, 함수 내부인지 등)은 중요하지 않고, 오직 해당함수를 호출하는 구문 앞의 점 또는 대괄호 표기가 있는지가 중요!
var obj1 = {
	outer: function() {
		console.log(this); // (1)
		var innerFunc = function() {
			console.log(this); // (2), (3)
		}
		innerFunc();

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

// (1) obj1, (2): 전역객체, (3): obj2

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

변수를 활용하는 방법

  • 내부 스코프에 이미 존재하는 this를 별도의 변수(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를 바인딩하지 않는 함수)

  • ES6 에서 처음 도입된 화살표 함수는 실행 컨텍스트를 생성할 때 this 바인딩 과정 자체가 없음 (따라서 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는 해당 콜백함수를 넘겨받은 함수(메서드)가 정한 규칙에 따라 값이 결정
  • 콜백 함수도 함수이기 때문에 this는 전역 객체를 참조하지만 (호출 주체가 없기 때문) 콜백함수를 넘겨받은 함수에서 콜백함수에 별도로 this를 지정하는 경우는 예외적으로 그 대상을 참조함
// 대상이 될 this 별도 지정 없음 : 전역객체
setTimeout(function () { console.log(this) }, 300);

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

// addListener 메서드는 콜백 함수 호출 시, 자신의 this를 상속 => this = addListener의 앞부분(button 태그)
document.body.innerHTML += '<button id="a">클릭</button>';
document.body.querySelector('#a').addEventListener('click', function(e) {
	console.log(this, e);
});

✅ 생성자 함수 내부에서의 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
profile
호기심 많은 귀차니즘의 공부 일기

0개의 댓글