자바스크립트에서의 this는 어디서든 사용할 수 있고, 상황에 따라 this가 바라보는 대상이 달라진다.
기본적으로 실행 컨텍스트가 생성될 때 함께 생성된다. 즉, this는 함수가 호출될 때 결정된다.
함수 안에서만 사용 가능하고 약속된 변수라고 할 수 있다. 변수처럼 작동하지만, this는 수정될 수 없다.
this는 전역객체(window / global)을 가르킨다.console.log(this);
console.log(window);
console.log(this === window); // true
this는 전역객체(window / global)을 가르킨다.// 함수 내부에서 this 호출
function a() {
console.log(this);
}
a();
// 외부함수 b의 내부함수 c 내부에서 this 호출
function b() {
function c() {
console.log(this);
}
c();
}
b();
// d 객체 내의 메소드 e 안에 있는 f함수 내부에서 this 호출
var d = {
e: function() {
function f() {
console.log(this);
}
f();
}
}
d.e();
this는 메소드 호출하는 주체를 가르킨다.this가 된다.var a = {
b: function() {
console.log(this);
}
}
a.b(); // a 객체를 가르킨다. {b: f()}
var a = {
b: {
c: function() {
console.log(this);
}
}
}
a.b.c(); // a.b의 객체를 가르킨다. {c: f()}
함수는 전역객체의 메소드다 라고 생각하면 편하다..ㅎ
this는 기본적으로 함수 내부에서와 동일하다.(기본적으로 함수의 this와 같다.)callback의 this를 명시한 경우 그에 따른다.this를 바인딩한 채로 callback을 넘기면 그에 따른다.var callback = function() {
console.dir(this);
};
var obj = {
a: 1,
b: function(cb) {
cb(); // window
cb.call(this); // 전혀 다른 결과
}
};
obj.b(callback);
setTimeout(callback, 100);
setTimeout(callback.bind(obj), 100);

bind가 없었던 시절에는 한 번 더 감싸서 변수를 이용하는 방식으로 활용했다.
this는 인스턴스(instance)를 가르킨다.function Person(n, a) {
this.name = n;
this.age = a;
}
var mook = new Person("mook", 30);
console.log(mook);

call, apply, bind 메소드에 대해 이해를 해야한다.
function a(x, y, z) {
console.log(this, x, y, z);
}
var b = {
c: "eee"
};
a.call(b, 1, 2, 3);
a.apply(b, [1, 2, 3]);
var c = a.bind(b);
c(1, 2, 3);
var d = a.bind(b, 1, 2);
d(3);
결과는 ▸Object {c: "eee") 1 2 3으로 동일하게 출력된다.
func.call(thisArg[, arg1[, arg2[, ...]]])
즉시 호출을 하는 명령이다.
첫번째 인자는 this를 받고, 두번째 인자부터 쭉 나열해서 받는다.
func.apply(thisArg, [argsArray])
즉시 호출을 하는 명령이다.
첫번째 인자는 this를 받고, 두번째 인자는 매개변수를 담은 배열을 받는다.
func.bind(thisArg[, arg1[, arg2[, ...]]])
call과 apply와 달리 bind는 새로운 함수를 생성(currying)할뿐 호출을 담당하지는 않는다.
첫번째 인자는 this를 받고, 두번째 인자부터 쭉 나열해서 받는다.
내부함수에서의 우회법
var a = 10;
var obj = {
a: 20,
b: function() {
console.log(this.a); // 20
function c() {
console.log(this.a); // 10
}
c();
}
}
obj.b();
obj.b()는 메소드 호출이라 obj 객체를 가리키고, c()는 일반함수 호출이라 전역의 a를 가르킨다.
그렇다면 함수 c안에서 obj을 바로볼 수 있게 this를 사용할 수는 없을까?
결론부터 말하자면, 스코프 체인(Scope Chain)을 이용해 우회가 가능하다.
var a = 10;
var obj = {
a: 20,
b: function() {
var self = this;
console.log(this.a); // 20
function c() {
console.log(self.a); // 10
}
c();
}
}
obj.b();
위와 같이 this를 self라는 변수에 담고, 변수 self를 활용하면 내부함수는 자신의 스코프에서 self을 바라보고 찾다가 없으면 스코프 체인을 타고 상위로 올라가며 this를 탐색한다.
var a = 10;
var obj = {
a: 20,
b: function() {
console.log(this.a);
},
c: () => {
console.log(this.a);
}
}
obj.b(); // 20
obj.c(); // 10
화살표 함수는 실행컨텍스트 생성시 this를 바인딩하지 않는다.
화살표함수 내부에 this가 존재하지 않기 때문에 스코프 체인에 따라 상위 컨텍스트의 this에 접근하게 된다.
따라서 obj.c()는 상위 컨텍스트의 this가 전역객체를 가리키기 때문에 10이 된다.
🔎 참고자료 🔎
- MDN
- 생활코딩
- PoiemaWeb
- javascript info
- 코어 자바스크립트
- 러닝 자바스크립트
- 인사이드 자바스크립트