
this키워드는 JavaScript뿐만 아니라 다양한 언어에서 사용되는 키워드이다. c++, Java에서는 보통 현재 객체 자신을 가르키는 용도로 쓰이는데 JavaScript에서는 어떤 용도로 쓰일까?
Java, c++에서는 현재 객체를 가르키는 용도의 this말고도 다른 용도로도 쓰이는데 JavaScript에서도 단순한 하나의 용도로 쓰는게 아닌 다양한 용도로 this키워드가 쓰인다.
JavaScript에서는 this가 쓰이는 함수를 어떤 방식으로 실행하느냐에 따라서 그 역할이 구별된다.
function foo() {
console.log(this);
}
foo();

일반함수에서 this를 호출하면 window객체가 호출된다.
즉, 일반함수에서 this는 글로벌객체인 window객체를 가르키는 것이다.
var name = "sangyeki"
function foo () {
console.log(this.name); // window.name
}
foo();
위와같이 전역 객체(window)에 "name"속성이 추가되고 "sangyeki"값을 할당하여서 출력이 "sangyeki"로 나온 걸 확인할 수 있다.
또한 위 "foo"함수 내부의 "this.name"은 결국 "window.name"과 동일하므로 "window.name"으로 작성해도 동일한 결과가 나온다.
this키워드는 객체 내부에서 객체 자신을 가르키는 용도로 사용할 수 있다.
let name = "sangyeki";
let f = {
name : "kim",
foo : function(){
console.log(this.name);
}
}
f.foo();
위와같이 "f"객체의 속성인 "foo"메서드의 this키워드는 "f"객체를 가르키게 된다.
그래서 "this.name"은 결국 "f"객체의 "name"속성을 참조하고 "kim"이 출력된다.
let name = "sangyeki";
function foo () {
console.log(this.name);
}
let san = {
name : "yoon",
foo : foo
}
let yek = {
name : "young",
foo : foo
}
san.foo();
yek.foo();
let tae = san.foo;
tae();
"san"객체의 "yoon"과 "yek"객체의 "young"은 객체 안에 있는 "foo"속성이 function foo()로 초기화 되었기 때문에 위와같은 출력값이 나온다.
"tae"변수는 "san"객체에 있는 "foo"변수만 할당받은거라 "tae"변수에서의 function foo()메서드는 결국 전역 객체(window)를 참조하게 되어서 아무런 값이 안나오게 된다.
명백한 바인딩이란 this의 역할을 우리가 직접 명확하게 지정해준다는 뜻이다.
이는 call, bind, apply과 같은 메서드를 사용하여 할 수 있다.
function test(x,y){
var result = x+y;
this.result = result;
}
test(1,2);
console.log(window.result);
var p1 = {name : "apple"};
test.apply(p1, [3, 4]); //이때 호출되는 this는 p1
console.log(p1.result);
var p2 = { name : "banana"};
test.call(p2, 5, 6); //이때 호출되는 this는 p2
console.log(p2.result);

call, apply같은 메서드는 첫번째 인자로 함수의 this키워드를 어떤 객체에 지정해줄 것인지 정해줄 수 있다.
즉, 함수에서 사용하는 this랑 apply, call메서드의 첫번째 인자랑 바인딩 해주는 것이다.
그래서 위와같이 출력이 3,7,11이 나오는 것이다.
function test(x,y){
var result = x+y;
this.result = result;
}
위 부분에서 일반함수는 call, apply와 같이 사용하면 해당 함수의 this키워드는 call, apply의 첫번째 인자를 가르키게 되는 것이다.
apply메서드는 여러 인자를 한 배열에 받고,call메서드는 여러 인자를 배열이 아닌 나열해서 받는다.
함수를 실행할때 함수명() 같은 형태로 실행할 수도 있지만 new키워드를 사용해서 생성자 함수로 만들어 사용할 수도 있다.
이 경우에 this는 빈 객체가 된다.
function Person() {
console.log(this);
}
new Person();
위와 같이 빈 객체가 호출된다.
즉, 생성자 함수 안에서의 this는 해당 함수를 를 통해서 생성한 객체가 호출된다.
그럼 빈 객체에다가 속성을 어떻게 추가할 수 있을까?
function Person() {
console.log(this.age);
this.age = 100;
console.log(this.age);
}
new Person();
생성자 함수 내부에서 this.속성을 정의하면 해당 속성이 정의된 객체가 생성된다.

console.dir(this)를 생성자 함수 내부에서 실행하면 위와같이 "Person"객체가 생겼고 "age"속성이 추가된것을 확인할 수 있다.
만약 생성자 함수를 통해서 생성한 객체를 변수에다가 저장해서 사용하고 싶을땐 어떻게 해야 할까?
function Person() {
this.name = "sangyeki";
console.log(this);
}
let ken = new Person();
console.log(ken);

new Person()을 통해서 만들어져 반환된 객체를 변수에다가 복사해서 사용할 수 있다.
그럼 만약 생성자 함수 내부에서 return을 하면 어떤 결과가 나올까?
function Person() {
this.name = "sangyeki";
return 42;
}
let ken = new Person();
console.log(ken);
생성자 함수 내부에서 객체가 아닌 값을 return을 정의해도 실상 반환되는 값은 this 즉, 생성자함수를 통해 만든 객체가 반환된다.
이는 생성자 함수의 특징이다.
그럼 생성자 함수를 통해 만든 객체가 아닌 임의로 지정한 객체를 반환하면 어떻게 될까?
function Person() {
this.name = "sangyeki";
return {age : 27};
}
let ken = new Person();
console.log(ken);
생성자 함수를 통해서 리턴한 값이 객체이면 this 즉, 생성자 함수가 생성한 객체를 반환하는게 아닌 return문에서 반환된 객체를 반환한다.
1. 일반함수 즉, 함수선언문으로 선언한 함수내부에서의 this는 window를 참조한다.
2. 일반함수의 중첩함수에서의 this도 "window"를 참조한다.
function Person() {
function Animal() {
console.log(this);
}
Animal();
}
Person();

3. 객체안에서의 this키워드는 객체의 속성을 가르킨다. 그럼 const, let으로 지정한 전역변수로 어떻게 접근할까?
const number = 42;
const score = 100;
const obj = {
number: 21,
score: 50,
func: function () {
console.log(this.number);
console.log(number);
},
};
obj.func();
전역변수에서 지정한 변수명으로 참조하면 된다.
4. 콜백함수안에서 this키워드는 어디를 참조하고 있을까?
function timeFunc() {
setTimeout(() => {
console.log(this);
}, 1000);
}
timeFunc();
콜백함수 안에서 this키워드는 전역객체를 참조하고 있다.
사실 this키워드의 개념에 대해서 JavaScript를 처음 배웠을때 말고는 사용한적이 없었는데 최근에 들은 강의에서 apply, call을 통한 this키워드 코드로직이 있어서 해당 개념에 대해서 다시 복습할 겸 정리해보았다.
this키워드도 잘 쓰면 요긴하게 쓸거 같은데 잘 쓰기까지가 허들이 약간 있다고 느껴진다.
또한 this키워드가 여러 용도로 쓰이다보니 프로젝트에서 서로간의 코드리뷰를 할때 면 대면 으로 코드리뷰를 하지 않는이상 특정 용도를 파악하는데 상당히 난항을 겪을거 같기도하다.(물론 이건 아직 미숙한 내 문제일 확률이 높을거같다)