Javascript의 this
Javascript 에서의 this 는 우리가 흔히 처음접하게 되는 언어인 Java 의 this 와 사용법이 달라 혼동이 올 때가 있다.
Java 와 같은 객체지향 언어에서 this 는 class 로 생성된 인스턴트 자신이며, class 밖에서 사용 할 수 없다.
Javascript 의 this는 함수의 현재 실행 컨텍스트를 의미하는데 예제 코드를 통해 어떻게 다른지 살펴보자
1. 일반적인 함수
function defaultFunc() {
console.log(this) // window or global
}
이 함수의 실행 컨텍스트는 전역 객체이므로, 브라우저 환경에서는 window , Node 환경에서는 global 객체가 될 것이다.
2. strict 모드에서의 함수 실행
function strictMode() {
'use strict';
console.log(this) // undefined
}
3. 내부 함수
const obj = {
fruit: "apple",
test: function() {
console.log(this) // obj
function innerFunction() {
console.log(this) // window or global
}
innerFunction()
}
}
test 의 실행 컨텍스트는 obj 이므로 this 는 obj 이며, test 내부에 있는 innerFunction 은 메소드가 아니고 함수 실행 이기때문에 컨텍스트는 window or global 이 된다.
4. 메소드
const methodTest = {
call: function() {
console.log(this === methodTest) // true
}
}
methodTest.call()
call 메소드의 실행 컨텍스트 객체인 methodTest 가 this 가 된다.
메소드와 함수실행을 구분하는 방법은 메소드는 참조한다는 기호인 콤마가 있고 함수실행은 없다.
someMethod.call() // method
someFunction() // function
4-1 주의
const methodTest = {
fruit: "apple",
run: function() {
console.log(this.fruit)
}
}
const runTest = methodTest.run
runTest()
위와 비슷하지만 methodTest 의 run 이라는 메소드를 runTest 라는 변수에 담아 호출하였을때 this 는 어떻게 될까?
methodTest 가 메소드 일지라도 runTest() 는 함수 호출이기 때문에 this 는 전역객체가 되고 전역객체에는 fruit 가 없기 때문에 undefined 가 콘솔에 찍힌다.
5. 생성자
class Person {
constructor() {
this.userName = "John"
console.log(this) // Person{}
}
}
const instance = new Person()
console.log(instance.userName) // "John"
new Person() 은 생성자 실행이다. 이 때 컨텍스트는 Person 의 인스턴스이다.
5-1 주의
function Person() {
this.userName = "Jone"
return this
}
const instance = Person()
console.log(instance.userName)
몇몇 함수는 함수를 실행해도 인스턴스를 반환하는 함수가 있다.
위의 Person 함수는 함수 실행을 해도 객체가 반환 된다.
생성자 실행으로 반환되는 this 는 Person 인스턴스이지만, 함수 실행으로 반환되는 this 는 전역 오브젝트이다.
그래서 "Jone" 이라는 문자열을 this.userName 에 할당했는데, window.userName = "Jone" 을 한 것이니 주의하자.
이를 조금 쉽게 해결하려면 instanceof 키워드를 사용하면 되는데,
function Person() {
if(!(this instanceof Person)){
throw Error("Incorrect invocation" , { cause : "해당 인스턴스가 아닙니다" })
}
this.userName = "Jone"
return this
}
const instance = Person()
console.log(instance.userName)
해당 키워드로 this가 Person 타입의 객체가 맞는지 방어코드를 추가하면 막을 수 있다.