[자바스크립트 기초-5] this에 대해 알아보자

[자바스크립트 기초-5] this에 대해 알아보자

자바스크립트 코드를 읽다보면 this가 자주 언급되는 것을 볼 수 있습니다. this는 함수 안에서 사용되는데, 처음엔 그 사용법이 헷깔릴 수 있습니다. 간단하게 말하면 this는 해당 함수를 실행한 오브젝트를 뜻합니다.

var a = "Hello"

function test() {
    var a = "Bye";
    
    console.log(this.a);
}

test();
// 결과 -> "Hello"

위 코드를 실행해보면 결과가 test 함수 안에 로컬 변수로 정의된 a의 값이 아니라 글로벌 변수로 정의된 a의 값이 출력되는 것을 알 수 있습니다. test가 글로벌로 지정된 함수이기 때문인데, 그럼 이 때 this는 무슨 오브젝트를 말하는 것일까요?

정답은 window 입니다. 모든 글로벌 변수들은 window 오브젝트에 소속됩니다.

다음 코드에선 오브젝트 안에 메소드로 실험을 해봅니다.

var a = "Hello";

var obj = {
    a: "Bye",
    test: function() {
        console.log(this.a);
    }
}

obj.test();
// 결과 -> Bye

위 결과에서 알 수 있듯이 이번엔 obj 오브젝트 속성으로 지정된 a의 값이 출력되는 것을 알 수 있습니다. 그 이유는 test 메소드 안에서 정의한 thisobj 오브젝트를 가리키고 있기 때문입니다.

그렇다면 글로벌 변수에 오브젝트 메소드를 지정한 후 실행하면 어떻게 될까요?

var a = "Hello"

var obj = {
    a: "Bye",
    test: function() {
        console.log(this.a);
    }
}

var test2 = obj.test;

test2();
// 결과 -> Hello

왜 글로벌 변수로 지정된 a의 값이 출력된걸까요? 그 이유는 test2라는 함수는 글로벌로 오브젝트 (window)가 실행을 했기 때문입니다. 그래서 thiswindow를 뜻하게 되는거죠. 위의 test2 함수는 아래의 코드와 동일한 뜻을 가집니다.

var test2 = function() {
    console.log(this.a);
}

그렇다면 obj 오브젝트의 메소드인 test를 글로벌 변수에 참조하였을 때, test 메소드의 thiswindow가 아닌 obj를 뜻하게 하기 위해선 어떻게 해야할까요?

var a = "Hello"

var obj = {
    a: "Bye",
    test: function() {
        console.log(this.a);
    }
}

var test2 = obj.test.bind(obj); // <- bind 사용

test2();
// 결과 -> "Bye"

위의 코드처럼 bind를 이용해서 test 메소드의 this가 항상 obj를 참조하도록 강제해주면 됩니다. 그러면 아무리 test2 함수가 글로벌로 실행이되더라도, objtest 메소드 안의 this는 항상 obj를 뜻하게 됩니다.

그럼 반대로 obj의 메소드인 test를 직접 실행할 때, this가 다른 오브젝트를 참조하도록 하는 방법은 없을까요?

var a = "Hello"

var obj = {
    a: "Bye",
    test: function() {
        console.log(this.a);
    }
}

obj.test.apply(window);
// 결과 -> Hello

위의 코드처럼 apply를 이용해주면 됩니다. 실행하려는 메소드 마지막에 apply를 사용하여 window 오브젝트를 지정해주면 thisobj가 아니고 window를 참조하게 됩니다.

물론 window 오브젝트가 아닌 다른 오브젝트도 가능합니다.

var a = "Hello"

var obj = {
    a: "Bye",
    test: function() {
        console.log(this.a);
    }
}

var obj2 = {
    a: "World"
}

obj.test.apply(obj2);
// 결과 -> World

이렇듯 applyobj2를 지정해주면, obj.testthisobj2를 참조하게 되어 "World"를 출력하게 됩니다.

bind를 사용하든 apply를 사용하든, 중요한건 적용시키는 오브젝트가 bindapply를 사용하는 메소드를 갖고 있는 오브젝트와 같은 이름의 변수를 갖고 있는 것이 중요합니다.


처음에는 헷깔릴 수 있지만 자바스크립트에서 this는 아주 중요한 컨셉이기 때문에, 이것 저것 실험해보면서 익숙해져야 합니다.