자바스크립트를 배우면서 "this"
에 대해 많이 어려워하고 아직도 잘 모르고있는것 같습니다. 우리는 이 "this"
를 객체의 메서드에서 자주 볼 수 있습니다.
let user = {
name: "Uiseop",
born: 1997,
sayHi() {
console.log(this.name); *(1)*
// console.log(user.name); // 동일하다
}
};
user.sayHi(); // Uiseop
메서드 내부에서 "this"
키워드를 사용하면 객체에 접근할 수 있습니다.
이때 this는 user
.sayHi();에서 user
를 가리킵니다. 메서드의 점(.) 앞을 가리키고 있는 것 입니다. 정확히는 메스드를 호출할 때 사용되는 객체를 나타냅니다.
이때 위의 코드 (1)
부분에서 "this"
를 사용하지 않고 외부 변수인 user
를 참조하는, "this"
를 user
라고 변경해도 같은 결과가 나타납니다.
이게 가능한 이유는 함수를 실행하거나, 코드블럭을 진입할 때, 스크립트를 실행할 때 자바스크립트가 생성하는 렉시컬 환경(Lexical Enviroment) 을 먼저 이해하시면 좋겠습니다.
다시 돌아와서 그럼 왜 외부 변수인 user
를 사용하지 않고 이해하기도 어렵운 "this"
를 사용할까요?
외부 변수인 user
로 객체안의 프로퍼티를 접근하려고 하면 예상치 못한 에러가 발생할 수 있습니다. 가령 객체 user
를 다른 변수에 할당(admin=user)
하고, user
를 name이라는 프로퍼티가 없는(user=null)
다른 값으로 덮어썼다고 가정합니다.
그러면 admin
이 참조하는 객체의 sayHi()
메서드는 user.name
을 호출하고 있는데 user에는 name이라는 프로퍼티가 없기때문에 에러가 나고, 에러를 해결하기 위해서는 같은 코드
를 또 귀찮게 작성해야한다는 문제가 발생합니다.
하지만 애초에
user.name
대신this.name
을 인수로 받았다면 중복되는 코드를 작성하는 낭비를 줄일 수 있습니다.
자바스크립트에서 모든 함수에서 "this"
를 사용할 수 있습니다. 왜냐하면 "this"
는 런타임에 결정되기 때문입니다. 컨텍스트에 따라 달라지죠. 따라서 동일한 함수라도 다른 객체에서 호출했다면 "this"
가 참조하는 값이 달라집니다.
"this"
가 런타임에 결정되면 좋은 점도 있고 나쁜 점도 있습니다. 함수를 하나만 만들어서 여러 객체에서 재사용할 수 있다는 것은 분명한 장점이지만, 이러한 유연함이 저한테는 너무 어렵게 느껴지는게 단점입니다.
정답
비엄격모드 undefined
엄격모드 Error: Cannot read property 'name' of undefined
에러가 발생하는 이유는 this
값을 설정할 땐 객체 정의가 사용되지 않기 때문입니다. this
은 호출 시점에 결정됩니다.
위 코드에서 makeUser()
의 this
는 undefined
입니다. 객체의 메서드로 사용되지 않았기 때문(참조하는 객체가 없음)입니다. this
은 함수 내의 코드 블록에 상관없이 모두 함수의 현재 this
값을 가져오기 문에 ref: this
도 마찬가지로 undefined를 가져옵니다.
에러가 발생하지 않게 하려면 ref또한 메서드가 되어 객체를 참조할 수 있으면 됩니다.
바로 앞에서 모든 함수에서
"this"
를 사용할 수 있다고 했는데 화살표 함수에선 못쓴다?
화살표 함수는 일반 함수와는 달리 고유한"this"
를 가지지 않습니다. 화살표 함수에서 "this"
를 참조하면, 화살표 함수가 아닌 외부의 일반 함수에서 "this"
값을 가져옵니다.
일반 함수 sayHi()의 "this"
는 user를 가리키고 있고, 화살표 함수인 arrow 함수는 외부 함수의 "this"
인 user를 참조하고 있기 때문에 결과가 user.name
이 나오는것을 확인할 수 있습니다.
- 모든 함수에서는
"this"
를 사용할 수 있습니다.- 객체안의 메서드는
"this"
를 통해 현재 객체에 접근할 수 있습니다.- 함수를 선언할 때
"this"
를 사용할 수 없습니다. 다만, 함수가 호출되기 전까지"this"
엔 값이 할당되지 않습니다.- 별개의
"this"
가 만들어지는 건 원하지 않고, 외부 컨텍스트에 있는"this"
를 사용하고 싶을 경우화살표 함수
가 유용합니다.