맨날 this를 사용할 때 헷갈려서 공부하며 정리를 해봤습니다.
자바스크립트에서 this의 값은 함수를 호출한 방법에 의해 결정된다. 중요한 것은 선언했을 때가 아닌 어떤 객체가 호출했느냐가 this값을 결정한다는 것이다. 아래 person 객체를 보자.
const person = {
name: "kingkong",
introduce: function (){
console.log(`My name is ${this.name}`)
}
}
person.introduce()//'My name is kingkong'
위 객체를 보면 person 객체가 introduce를 호출 했기 때문에 this가 person 객체를 가르키게 된다. 다음 코드를 보자
const person = {
name: "kingkong",
introduce: function() {
console.log(`My name is ${this.name}`);
}
}
const introduce2 = person.introduce;
introduce2()//window 객체
왜 이럴까? 바로 introduce2가 window객체에서 호출되었기 때문이다. 이처럼 this는 어디서 호출되었는지를 바탕으로 그 객체를 가리키게 된다. 이번에는 DOM을 예시로 보자.
<!DOCTYPE html>
<html>
<body>
<button class="btn">Click me</button>
<script>
const btn = document.querySelector('.btn');
btn.addEventListener('click',person.introduce)
</script>
</body>
</html>
myname is 이 출력될 것이다. introduce를 호출한 객체가 button이기 때문이다.
이렇듯 this는 "호출" 한 객체를 가르킨다.
그렇다면 화살표함수에서 this는 어떨까? 화살표 함수에는 this가 없다. 그래서 화살표 함수에서 this를 사용하면 화살표 함수를 선언한 함수의 this를 사용한다. 함수 scope에 this가 없는데 this를 사용하면 상위 스코프의 this를 사용하게 되는 것이다.
const person = {
name: "kingkong",
introduce:()=>{
console.log(`my name is ${this.name}`)
}
}
person.introduce()//my name is 만 출력된다. this가 없기 때문이다.
때문에 this를 사용할 때는 화살표 함수와 일반 함수를 잘 선택해서 써야 한다.
node.js에서 this는 조금 다르게 동작한다. 결론부터 이야기 하자면 전역 환경에서는 module.exports를 함수안에서는 global을 가르킨다.
//Node
console.log(this === module.exports, this === exports);//true, true
function func(){
console.log(this === global);//true
}
실제로 개발했던 코드를 바탕으로 this값이 무엇인지 알아보자.
유저 로그인 라우터
router.post("/login", async (req, res) => {
try {
let user = await UserModel.findOne({ email: req.body.email });
console.log("abaaaaaa");
const result = await user.comparePassword(req.body.password);
if (!result) {
return res
.status(200)
.json({ success: false, message: "비밀번호가 일치하지 않습니다" });
}
user = await user.generateToken();
console.log("userToken:", user.token);
return res.status(200).cookie("x_auth", user.token).json({ success: true });
} catch (error) {
console.error(error);
return res.status(400).json({ success: false, error });
}
});
유저 스키마 methods
userSchema.methods.comparePassword = (password) => {
const user = this;
return new Promise(async (resolve, reject) => {
try {
console.log("bcrypt:", user.password);
const result = await bcrypt.compare(password, user.password);
resolve(result);
} catch (error) {
reject(error);
}
});
};
유저스키마 메서드에서 this를 사용했다. 여기서 this는 무엇일까? 여기서 this는 user document다. login 라우터를 보면 user.comparePassword()로 user document가 comparePassword()를 호출하는 것을 볼 수 있다. 그래서 this가 user document가 되고, user.password에 접근하여 복호화할 수 있는 것이다.
혹시 틀린 부분이 있다면 댓글 부탁드립니다.