함수의 암시적 파라미터는 4편으로 이루어져 있습니다.
들어가며
지난 글에서는 자바스크립트 함수에서 암시적인 파라미터인 arguments에 대해서 알아봤는데요
이번 포스팅에서는 this에 대해서 설명해 보겠습니다.
this
함수가 호출되면 암시적인 파라미터인 arguments외에 this가 전달됩니다.
예제1
function myThis() {
console.log(this);
}
myThis();
예제2
const obj = {
value: 10,
myThis: function () {
return this;
},
};
console.log(obj.myThis() === obj);
예제 1과 예제 2에서 콘솔에 찍히는 값이 무엇일까요?
this의 값을 결정하는 기준은 무엇일까요?
함수를 호출하는 방법에 따라 결정되는 this의 값
함수를 호출하는 방식에는 크게 4가지 방식이 있습니다.
- 함수로서 호출(As a function): myThis() 처럼 함수를 직접 호출하는 방식
- 메서드로서 호출(As a method): obj.myThis() 처럼 호출을 객체에 연결하여 호출
- 생성자로서 호출(As a constructor): new MyThis() 처럼 새로운 객체를 생성하여 호출
- call 및 apply를 통해서 호출(Via this function’s apply or call method): Function 객체의 call, apply 메서드를 통해서 호출
하나하나 살펴보겠습니다.
함수로서 호출(As a function)
함수로서 호출한다는 것은 그냥 우리가 평소에 함수를 사용하는 방식입니다.
함수로서 함수를 호출하면 this의 값은 비 엄격 모드, 엄격 모드에 따라서 2가지가 될 수 있습니다.
- 비 엄격 모드
- 엄격 모드 (Strict mode)
비 엄격 모드
function sayHi() {
console.log(this === window); // true
}
sayHi();
let sayHi = function () {
console.log(this === window); // true
};
sayHi();
비 엄격 모드에서는 위 예제처럼 브라우저의 전역객체인 window로 출력됩니다.
엄격 모드
'use strict';
function sayHi() {
console.log(this === undefined); // true
}
sayHi();
let sayHi = function () {
console.log(this === undefined); // true
};
sayHi();
하지만 “use strict”를 사용한 엄격 모드에서는 undefined가 출력됩니다.
메서드로서 호출
예제 2처럼 함수가 객체의 속성(property)에 할당되고 해당 속성을 사용해서 함수를 호출하면 함수가 해당 객체의 메서드로 호출됩니다.
메서드로서 호출에서 중요한 점은
객체의 메서드로 함수를 호출하면 해당 객체는 함수 컨텍스트가 되고 this 파라미터를 통해 함수 내에서 사용할 수 있다
라는 것입니다. 아래 코드를 통해서 무슨 뜻인지 알아볼까요?
// 함수 컨텍스트를 확인하기 위한 함수
function whatsMyContext() {
return this;
}
// 0. 함수로서 호출
console.log(whatsMyContext() === window); // ?
// 1. whatsMyContext 함수를 참조
const getMythis = whatsMyContext;
console.log(getMythis() === window); // ?
// 2. 객체의 메서드로 참조해서 호출
const obj = {
getMyThis: whatsMyContext,
};
console.log(obj.getMyThis() === obj); // ?
whatsMyContext는 함수 컨텍스트를 확인하기 위해 단순히 this만을 리턴합니다.
0번의 결과
0번의 경우에는 비 엄격 모드에서 함수를호출 했으므로 전역 객체인 window가 출력 될 것 같습니다. 결과를 돌려보면 true입니다.
1번의 결과
1번의 경우는 단순히 whatsMyContext 함수를 참조하는 변수입니다. 결과는 true입니다.
2번의 결과
2번의 경우는 obj라는 객체의 getMyThis라는 속성에 값으로 whatsMyContext 함수를 참조하였습니다.
이와 같은 경우를 메서드로서 함수를 호출 한다고 합니다.
여기서 주의해야 할점은 obj 객체의 메서드는 getMyThis라고 한다는 것입니다. whatsMyContext가 메서드가 된 것이 아닙니다.
그래서 결과를 살펴보면 true 입니다.
true인 이유는 위에서 설명한 중요한 점에 정확히 일치합니다.
객체의 메서드로 함수를 호출하면 해당 객체는 함수 컨텍스트가 되고 this 파라미터를 통해 함수내에서 사용 할 수 있다
해당 객체 obj가 whatsMyContext의 함수 컨텍스트가 되었습니다.
다시 한번 코드를 통해서 확인 해보겠습니다.
// 3. 2번과 동일하지만 새로운 obj2라는 객체의 매서드로 호출
const obj2 = {
getMyThis: whatsMyContext,
};
console.log(obj2.getMyThis() === obj); // false
console.log(obj2.getMyThis() === obj2); // true
obj, obj2에서 메서드로서 함수를 호출하여 각각 다른 함수 컨텍스트가 형성되었습니다.
이렇게 메서드로서 함수 호출을 통해서 메서드의 소유 객체를 참조할 수 있고, 각각 다른 객체에 대해 정확히 동일한 처리를 수행하기 위한 함수의 복사본을 반복적으로 만들 필요가 없습니다. 이를 통해서 객체지향 자바스크립트를 구현할 수 있습니다.
위 예제들은 jsfiddle에서 확인해주세요
마치며
암시적인 파라미터 this의 값은 함수가 호출되는 방식으로 결정되는데 이번 포스팅에서는
- 함수로서 호출
- 메서드로서 호출
에 대해 알아봤습니다.
다음 포스팅에서는 생성자로서 호출, call 및 apply를 통한 호출을 알아보겠습니다.
읽어주셔서 감사합니다.