📌 this 란
실행할 코드에 제공할 환경 정보들을 모아놓은 객체를 실행 컨텍스트(execution context) 라고 부른다. 자바스크립트 내부에서 이런 실행 컨텍스트를 스택(Stack)으로 관리하고 있으며, 실행되는 시점에서 자주 변경되는 실행 컨텍스트를 this 가 가리키고있다.
스택 중 콜스택(Call Stack)에 쌓아올리며 가장 위에 쌓여있는 컨텍스트와 관련된 코드를 실행하는 방법으로 코드의 환경과 순서를 보장 할 수 있다.
객체 지향 언어에서 this는 클래스로 생성한 인스턴스를 말하지만, 자바스크립트에서 this는 언제 어디서나 사용할 수 있다.
this는 실행되는 코드의 실행 컨텍스트를 가리킨다!
💡 실행 컨텍스트 속 3가지
VariableEvironment
LexicalEvironment
ThisBinding 👉🏻 오늘 이해할 것
1. default binding
기본적으로 this는 전역 객체를 가리킨다. 브라우저 환경에서 this는 window를 가르키고, 노드 환경에서 this는 global을 가르킨다.
Browser
Node
2. 메서드 내부에서의 this
함수 | 함수는 호출의 주체가 없고 함수 그 자체로 독립적인 기능을 수행한다. |
메서드 | 반대로 메서드는 호출 주체가 있으며 자신을 호출한 대상 객체에 대한 동작을 수행한다. |
함수
함수명();
// CASE1 : 함수
// 호출 주체를 명시할 수 없기 때문에 this는 전역 객체를 의미
var func = function (x) {
console.log(this, x);
};
func(1); // Window { ... } 1
메서드
객체.메서드();
// CASE2 : 메서드
// 호출 주체를 명시할 수 있기 때문에 this는 해당 객체(obj)를 의미
// obj는 { method: func }
var obj = {
method: func,
};
obj.method(2); // { method: [Function: func] } 2
예외
메서드 내부에서도 독립적으로 호출한다면 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
3. this 우회
화살표(=>)함수는 실행 컨텍스트를 생성할 때 바인딩 과정이 없다. 일반함수와 화살표 함수의 가장 큰 차이점은 this binding 의 여부이다.
var obj = {
outer: function () {
console.log(this); // (1) obj
var innerFunc = () => {
console.log(this); // (2) obj
};
innerFunc(); //함수로 호출해도 전역객체가 아닌 호출객체를 가리킴
}
}
obj.outer();
화살표 함수 예외
obj 객체 안 print 메서드를 화살표 함수로 선언할 경우 this는 전역 객체를 가리킨다.
var obj = {
names: ["seo"],
text: "님 안녕하세요",
print: () => { console.log(this.text) } // undefined
}
obj.print()
4. 콜백함수 this
콜백함수도 함수이기때문에 this가 전역 객체를 가리키지만 콜백함수를 넘겨 받은 함수에서 콜백함수에 별도로 this를 지정해준 경우 예외로 그 대상을 참조한다.
별도의 지정이 없어 전역 객체를 가리킨다.
setTimeout(function () { console.log(this) }, 300);
[1, 2, 3, 4, 5].forEach(function(x) {
console.log(this, x);
});
addEventListener 메서드는 콜백함수 호출 시, 자신의 this를 상속. 따라서 this는 button 을 가리킨다.
document.body.innerHTML += '<button id="a">클릭</button>';
document.body.querySelector('#a').addEventListener('click', function (e) {
console.log(this, e);
});
5. 명시적 this 바인딩
자동으로 부여되는 상황별 this의 규칙을 깨고 this에 별도의 값을 저장하는 방법
call, apply, bind
call | 호출 주체인 함수를 즉시 실행 | 첫번째 인자로 실행 컨텍스트를 인자로 전달 |
apply | call과 동일하되 배열 형태로 넘김 | |
bind | 즉시 호출하지 않고, 함수에 this를 미리 적용하거나 부분적으로 적용 |
5-1. Call 메서드
var obj = {
string : "free",
value : function(){
console.log(this.string);
},
}
var obj2 = {
string : "not free",
}
obj.value(); //free
obj.value.call(obj2); //not free
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}; // { 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
5-2. Apply 메서드
var func = function (a, b, c) {
console.log(this, a, b, c);
};
func.apply({ x: 1 }, [4, 5, 6]); // { x: 1 } 4 5 6
var obj = {
a: 1,
method: function (x, y) {
console.log(this.a, x, y);
}
};
obj.method.apply({ a: 4 }, [5, 6]); // 4 5 6
5-3. Bind 메서드
call과는 다르게 즉시 호출하지는 않고 넘겨받은 this 및 인수들을 바탕으로 새로운 함수 를 반환하는 메서드
var func = function (a, b, c, d) {
console.log(this, a, b, c, d);
};
func(1, 2, 3, 4); // window ... 1, 2, 3, 4
// 함수에 this 미리 적용
var bindFunc1 = func.bind({ x: 1 }); // 바로 호출X
bindFunc1(5, 6, 7, 8); // { x: 1 } 5 6 7 8
// 부분 적용 함수 구현
var bindFunc2 = func.bind({ x: 1 }, 4, 5); // 4와 5를 미리 적용
bindFunc2(6, 7); // { x: 1 } 4 5 6 7
bindFunc2(8, 9); // { x: 1 } 4 5 8 9
'javascript' 카테고리의 다른 글
[자바스크립트] 콜백함수 이해하기 (0) | 2024.05.09 |
---|---|
[자바스크립트] 배열 reduce() 사용법과 예제 (2) | 2024.04.26 |
[자바스크립트] 배열의 sort(), slice() (0) | 2024.04.25 |
[자바스크립트] map() 함수로 배열 순환하기 (0) | 2024.04.23 |
[자바스크립트] async 와 await 정리 (1) | 2024.04.19 |