Posts this
Post
Cancel

this

this

자바 스크립트에서 this 는 기본적으로 전역 객체를 가리킨다. (node.js : global, browser : window)

함수 내에서 this 를 참조하더라도 마찬가지로 전역 객체가 찍히게 된다. this는 기본적으로 전역 객체를 가리키도록 되어있기 때문이다.

1
2
3
4
function a() {
    console.log(this); //Object [global] {...} or window {...}
}
a();


그러나, 예외적으로 this에 바인딩되는 객체가 변하는 순간들이 있다.


1) 객체의 함수 호출

객체의 함수를 호출하게 되면 this가 가리키는 객체가 해당 객체로 바뀌게 된다.

1
2
3
4
5
6
let obj = {
    a: function () {
        console.log(this); //{ a: [Function: a] }
    },
};
obj.a();


그런데 obj 객체의 함수 a 내부에 inner 함수를 생성하고 inner 함수 내부에서 this를 찍어보면 전역 객체가 찍히게 된다.

그 이유는 객체의 함수를 호출하는 것과 일반 함수를 호출하는 것의 차이인데 inner 함수는 객체 내부에서 호출될 뿐 객체의 함수가 아닌 일반 함수이기 때문에 default로 전역 객체를 가리키기 때문이다.

1
2
3
4
5
6
7
8
9
10
11
let object = {
    a: function () {
        console.log(this); //{ a: [Function: a] }

        function inner() {
            console.log(this); //Object [global] {...} or window {...}
        }
        inner();
    },
};
object.a();


2) 이벤트 리스너

이벤트 리스너에서 콜백 함수가 호출될때 this는 이벤트가 발생한 DOM Element를 가리키게 된다.

1
2
3
4
5
6
7
8
9
<button class="btn-test">click!</button>

<script>
    let buttonEl = document.querySelector('.btn-test');

    buttonEl.addEventListener('click', function () {
        console.log(this); //<button class=".btn-test">...
    });
</script>


하지만 이 경우에도 1) 의 경우처럼 내부에 새로운 inner 함수를 생성하면 해당 함수에서는 다시 this가 전역 객체를 가리키는 것을 볼 수 있다. 이 역시 inner 함수의 호출은 일반 함수의 호출이므로 default로 전역 객체를 가리키기 때문이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<button class="btn-test">click!</button>

<script>
    let buttonEl = document.querySelector('.btn-test');

    buttonEl.addEventListener('click', function () {
        console.log(this); //<button class=".btn-test">...

        function inner() {
            console.log(this); // window {...}
        }
        inner();
    });
</script>


3) 생성자 함수

생성자 함수를 new 로 실행하면 생성자 함수 내의 this 는 생성된 인스턴스를 가리키게 된다.

만약, new 를 붙이지 않으면 생성자 함수 내의 this 가 전역 객체를 가리키게 된다고 한다. (크롬에서는 new를 붙이지 않으면 아예 오류로 처리한다.)

1
2
3
4
5
6
7
8
9
10
function Person(name) {
    this.name = name;
}
Person.prototype.sayHello = function () {
    console.log('Hi, ' + this.name);
};

const me = new Person('Changhee');

me.sayHello(); // Hi, Changhee


또한, 1)에서 처럼 객체의 함수를 호출할 때 this가 해당 객체를 가리키게 되므로 me 객체의 name 값을 출력하게 된다.

1
2
const me = new Person('Changhee');
me.sayHello(); // Hi, Changhee


4) 명시적 변환

bind, call, apply 함수들은 this를 명시적으로 바꾸는 함수들이다.

해당 함수들을 사용하게 되면 this가 인자로 받은 객체를 가리키게 된다.

1
2
3
4
5
6
7
8
9
let obj = {};
function a() {
    console.log(this);
}

a(); // Object [global] {...} or window {...}
a.bind(obj).call(); // {}
a.call(obj); // {}
a.apply(obj); // {}


Arrow Function

Arrow Function(화살표 함수)을 사용하게 되면 상위 스코프의 this를 상속받게 된다.

따라서, 아래의 코드에서 inner 함수의 this 는 함수 a 의 this 를 상속받게 되어 object 객체를 가리키게 된다.

1
2
3
4
5
6
7
8
9
10
11
let object = {
    a: function () {
        console.log(this); // { a: [Function: a] }

        const inner = () => {
            console.log(this);
        };
        inner(); // { a: [Function: a] }
    },
};
object.a();


만약 이벤트 리스너의 콜백함수를 arrow 함수로 선언한다면?

이벤트 리스너 콜백함수의 this는 상위 스코프의 this인 window를 가리키게 되고 inner 함수 또한 window를 가리키게 된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<button class="btn-test">click!</button>

<script>
    let buttonEl = document.querySelector('.btn-test');

    buttonEl.addEventListener('click', () => {
        console.log(this); // window{...}

        const inner = () => {
            console.log(this); // window{...}
        };
        inner();
    });
</script>
This post is licensed under CC BY 4.0 by the author.

호이스팅

프로토타입 체인

Comments powered by Disqus.