2019. 06. 03 수정


1. 객체지향 언어인 JS

JS는 함수형 언어이자 객체지향 언어입니다.

이 글에서는 객체지향 언어로서 JS를 다루려고 하는데요.


JS의 모든 것들은 객체입니다.

var, let, const로 선언한 변수도 객체이며, 함수 등 모든 것들이 객체입니다.

( JS 객체에 대한 자세한 설명은 여기를 참고해주세요 ! )


JS는 모든 것들이 객체이기 때문에, 메서드를 호출한 객체가 저장되는 this에는 변수는 물론 함수, 브라우저의 window 객체 등이 될 수도 있습니다. 

그렇기 때문에 모든 것들이 this가 될 수 있으므로 this가 무엇이 될지는 항상 잘 살펴보아야 합니다.


this는 일반적으로 메서드를 호출한 객체가 저장된다고 알고 있는데요, 정말 그러한지 this에 대해 자세히 알아보도록 하겠습니다.





2. 다양한 this 예제

this는 자신을 호출한 객체가 저장되는 변수입니다.


1) 예제 1

var person = {
name: "victolee",
email: "asdf@example.com",
birth: "0225",
foo : function(){
console.log(this)
}
}

person.foo()

위의 예제에서 foo() 함수에 있는 this는 어떤 객체를 가르킬까요?

foo() 함수를 실행하기 위해서는 person 객체의 foo 프로퍼티를 참조해야 합니다.

즉, foo() 함수를 호출한 것은 person 객체이므로, this는 person 객체를 가르킵니다.




2) 예제 2

var x = 10;
function foo(){
this.x = 20;
x = 30;

console.log(x);
console.log(this.x);
console.log(window.x);
}

foo()

이번에는 출력 결과가 어떻게 될까요?

foo() 함수는 어떤 객체가 호출한 것이 아니기 때문에, this는 특정 객체를 가르키고 있지 않습니다.

일반 함수일 경우에는 window 객체를 this로 갖고 있습니다.


사실 예제에서 x를 선언한 부분은

  • x = 10
  • foo() 함수 내에서 this.x = 20 
  • foo() 함수 내에서 x = 30

window.x = 10

window.x = 20

window.x = 30

으로 작성한 것과 똑같기 때문에, 정답은 모두 30입니다.



3) 예제 3

<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script
src="https://code.jquery.com/jquery-3.2.1.min.js"
integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4="
crossorigin="anonymous"></script>
</head>
<body>
<button class="btn" value="foo">버튼</button>
</body>

<script>
$(".btn").click(function(){
console.log(this)
})
</script>

</html>

위의 예제는 jQuery 코드입니다.

button을 클릭 했을 시 jQuery의 click 이벤트가 실행되는데요, 콜백함수에 있는 this는 어떤걸 가르킬까요?


이 경우에 jQuery의 셀렉터인 class=btn인 버튼 요소가 this가 됩니다.

즉, 이벤트가 발생했을 때는 이벤트가 발생한 객체가 this입니다.





위의 내용을 정리하면 this가 생성되는 경우는 다음과 같습니다.

  • 객체가 메서드를 호출할 경우, 메서드를 호출한 객체가 this입니다.
  • 일반 함수인 경우, 브라우저 상에서 window가 this입니다.
  • 이벤트가 발생한 경우, 이벤트를 발생한 객체가 this입니다.





3. call() , apply() 메서드

메서드를 호출한 객체, 이벤트가 발생한 객체가 아니면 대부분의 this는 기본 값인 window가 될 것입니다. ( DOM에 한해서... )

call(), apply() 메서드는 this를 조작하는 메서드로서, 원하는 객체를 this로 할당하고 싶을 때 사용합니다.

또한 Function.prototype에 정의된 메서드이기 때문에 어떤 함수던 호출이 가능합니다.

someFunction.call( "지정할 객체", "인자1", "인자2", ... );

someFunction.apply( "지정할 객체", "배열");

call()apply() 메서드의 차이는 위와 같습니다.

함수를 호출할 때 this를 바꿔주는 기능은 같지만 매개변수로 인자들을 넘겨주느냐, 배열을 넘겨주느냐 차이입니다.


예제를 통해 두 메서드를 어떻게 사용하는지 살펴보도록 하겠습니다.

var person = {
name: "victolee",
email: "asdf@example.com",
birth: "0225",
foo : function(val1, val2, val3){
console.log(val1 + val2 + val3);
console.log(this);
}
}

person.foo.call(window, 3,6,9);

위의 예제는 call() 메서드를 사용하여 foo의 this 객체를 person에서 window로 변경했습니다.

foo() 메서드를 호출하기 위해서는 person 객체에서 호출해야 하므로 원래 this는 person일 것입니다.

그러나 call() 메서드를 호출할 때 첫 번째 인자로 window 객체를 전달했으므로 this는 window 객체로 변경됩니다.



var person = {
name: "victolee",
email: "asdf@example.com",
birth: "0225",
foo : function(){
sum = arguments[0] + arguments[1] + arguments[2]

console.log(sum);
console.log(this);
}
}

let arr = [3,6,9]
person.foo.apply(window, arr);

위의 예제는 apply() 함수를 호출하여 this 객체를 person 객체가 아닌 window 객체로 바꾼 코드이며, 설명은 동일합니다.



위의 두 예제에서 실제로 this 객체가 바뀌었는지 확인해보도록 하겠습니다.





이상으로 this 객체와 call(), apply() 메서드에 대해 알아보았습니다.

this는 자신을 호출한 객체를 의미하며, 기본 값으로 window 객체를 가르킵니다.

call(), apply() 메서드는 메서드를 호출할 때 this 객체를 조작할 수 있는 기능을 제공합니다.