this는 실행 컨텍스트가 생성될 때 결정된다. 이것을 this를 bind한다라고 한다.
전역공간에서의 this는 전역 객체를 가리킨다.
this에는 호출을 누가했는지에 대한 정보가 담긴다.
함수에서의 this, 메서드에서의 this
함수와 메서드는 비슷해보이지만 '독립성'에서 차이가 있다.
함수는 그 자체로 기능을 수행하지만, 메서드는 호출당한 객체에 대한 동작을 수행한다.
함수()
객체.메서드()
var func = function (x) {
console.log(this, x);
};
func(1);
var obj = {
method: func,
};
obj.method(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는 항상 전역객체를 가리킨다.
메서드의 내부함수에서의 this
메서드는 호출 주체가 있고 함수는 호출 주체가 없으므로 메서드 내부함수의 this도 전역객체를 가리킨다.
var obj1 = {
outer: function () {
console.log(this); // (1)
var innerFunc = function () {
console.log(this); // (2)
};
innerFunc(); // (2)
var obj2 = {
innerMethod: innerFunc,
};
obj2.innerMethod(); // (3)
},
};
obj1.outer(); //(1), (2)
1에서 메서드로서의 this 호출, 2에서 함수로서의 this 호출, 3에서 메서드로서의 this 호출을 하였기 때문에 위와 같은 결과가 나온다.
메서드의 내부함수에서 this 우회
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를 미리 저장해두어 우회한 모습을 볼 수 있다.
var obj = {
outer: function () {
console.log(this); // (1) obj
var innerFunc = () => {
console.log(this); // (2) obj
};
innerFunc();
},
};
obj.outer();
화살표 함수를 사용해서도 this를 우회할 수 있다.
일반함수에서의 this는 함수 그 자체를 의미하지만, ES6에서 추가된 화살표함수는 this를 outer로 잡기 때문에 this를 사진과 같이 출력해주는 것을 볼 수 있다.
콜백함수 호출 시 그 함수 내부에서의 this
// 별도 지정 없음 : 전역객체
setTimeout(function () { console.log(this) }, 300);
// 별도 지정 없음 : 전역객체
[1, 2, 3, 4, 5].forEach(function(x) {
console.log(this, x);
});
// 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);
});
콜백함수도 함수이기때문에 this를 전역 객체를 참조하지만, addEventListener는 만들어 질 때 호출한 주체의 element를 가리킨다.
따라서 위 코드에서 eventListener의 콜백함수에서의 this는 해당 버튼을 가리킨다.
명시적 this binding
//명시적 this binding
// call, apply, bind
// call
var func = function (a, b, c) {
console.log(this, a, b, c);
};
// no binding
func(1, 2, 3); // Window{ ... } 1 2 3
// 명시적 binding
func.call({ x: 1 }, 4, 5, 6);
var obj = {
a: 1,
method: function (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
// //명시적 this binding
// // call, apply, bind
// // call
var func = function (a, b, c) {
console.log(this, a, b, c);
};
func.apply({ x: 1 }, [4, 5, 6]);
var obj = {
a: 1,
method: function (x, y) {
console.log(this.a, x, y);
},
};
obj.method.apply({ a: 1 }, [7, 8]);
call()과 apply()는 사용방식이 조금 다를 뿐 같은 기능을 수행한다.
'2차 공부 > TIL' 카테고리의 다른 글
24.07.25 DOM / DOM 조작하기 (0) | 2024.07.25 |
---|---|
24.07.24 콜백지옥 / 동기, 비동기 (0) | 2024.07.24 |
24.07.23 콜/스택, 실행 컨텍스트 (0) | 2024.07.23 |
24.07.23 변수선언과 데이터 할당 / 불변하다 vs 불변하지 않다. (0) | 2024.07.23 |
24.07.22 JavaScript 문법 종합반 1, 2주차 (0) | 2024.07.22 |