this arguments
일반적으로 this는 현재 함수가 실행중인 객체 자신 을 지칭한다. 배운다. 좀 더 의미를 명확하게 하기 위해 주인공 이라는 표현을 사용하도록 하겠다.
객체의 this와 call()
Copy const student = {
no : 1,
name : "피카츄",
korean : 50,
english : 60,
math : 70
};
학생 객체가 있다(시각적 편의를 위해 생성자 함수를 쓰지 않았다).
객체에는 번호(no), 이름(name), 국어점수(korean), 영어점수(english), 수학점수(math) 를 저장할 수 있는 변수가 존재한다. 자바스크립트는 기본적으로 접근 제한이 존재하지 않으므로 각각의 변수에 대한 setter와 getter 메소드를 생성할 필요가 없다.
따라서 합계나 평균을 알고 싶다면 다음과 같은 코드를 작성해야 할 것이다.
Copy console.log("총점 : " + (student.korean + student.english + student.math) + "점");
backtrick 출력 구문을 사용하면 덧셈 정도는 없앨 수 있다
Copy console.log(`총점 : ${student.korean + student.english + student.math}점`);
이 경우 객체에 메소드를 추가하면 가독성과 효율성이 좋아진다.
Copy const student = {
no : 1,
name : "피카츄",
korean : 50,
english : 60,
math : 70,
//합계를 구하는 함수 추
total : function(){
return korean + english + math;
},
};
작성한 뒤 합계를 구하면 오류가 발생한다.
Copy console.log(`총점 : ${student.total()}점`);
//ReferenceError : korean is not defined
메소드 내부에 korean이 정의되지 않았다는 뜻이며, this 키워드를 추가하면 주인공의 정보임을 명시하면 오류 없이 출력된다.
Copy const student = {
no : 1,
name : "피카츄",
korean : 50,
english : 60,
math : 70,
total : function(){
return this.korean + this.english + this.math;
},
};
console.log(`총점 : ${student.total()}점`);//총점 : 180점
총점을 구하기 위해서 total 함수를 부를 때 다음과 같이 코드를 작성한다.
이 코드는 Function.prototype.call
함수를 사용하여 다음과 같이 표현할 수 있다.
Copy student.total.call(student);
따라서 다음과 같은 출력 구문도 정상 작동한다.
Copy console.log(`총점 : ${student.total.call(student)}점`);
두 방식에 대해 한글로 해석을 달아보면 다음과 같다.
Copy //[1] student의 total 함수를 실행한 반환값을 가져와라!
student.total()
//[2] 주인공을 student로 설정하고 student의 total 함수를 실행한 뒤 반환값을 가져와라!
student.total.call(student)
결과적으로는 동일한 실행 결과가 나온다. 하지만 [2] 방식은 주인공을 다르게 설정할 수 있다.
Copy const student1 = {
no : 1,
name : "파이리",
korean : 60,
english : 70,
math : 80,
total : function(){
return this.korean + this.english + this.math;
},
};
const student2 = {
no : 2,
name : "꼬부기",
korean : 50,
english : 60,
math : 70,
total : function(){
return this.korean + this.english + this.math;
},
};
console.log(`총점 : ${student1.total()}점`);//총점 : 210점
console.log(`총점 : ${student2.total.call(student1)}점`);//총점 : 210
코드를 단순하게 볼 수 있도록 prototype 등은 생략하였으며 이 코드는 매우 비효율적인 코드이다. 하지만 중요한 점은 함수를 실행할 때 주인공을 변경할 수 있다는 것이다.
callback 함수의 this
기존 student 객체에 공부를 위한 study 메소드를 추가한다.
Copy const student = {
no : 1,
name : "이상해씨",
type : "풀",
study : function(){
console.log(this.name + " 학생이 공부를 합니다");
},
};
공부가 끝나면 연속적으로 실행할 작업을 지정하기 위해 매개변수로 함수를 받아서 실행하도록 코드를 추가한다. typeof 를 이용한 타입 검사를 실시하였다.
Copy const student = {
no : 1,
name : "이상해씨",
type : "풀",
study : function(done){
console.log(this.name + " 학생이 공부를 합니다");
if(typeof done === 'function') {
done();
}
},
};
위와 같이 구성한 경우 공부만 시키거나 공부 후 해야할 일을 콜백 함수로 알려주면서 실행할 수 있다.
공부만 하도록 시키는 경우
공부 후 해야 할 일을 알려주는 경우
Copy student.study(function(){
console.log("공부 끝!");
});
실행하면 다음과 같이 결과가 나온다.
Copy 이상해씨 학생이 공부를 합니다
공부 끝!
그렇다면 this 에 대해서 알아보고 있는 현 상황에서 study에서의 this 와 콜백 함수에서의 this 는 어떤 대상을 가리킬까?
출력해보면 study() 에서는 student 객체가, callback 함수에서는 window 객체가 출력된다. window 는 웹 브라우저의 root 객체일 뿐 다른 환경이라면 다른 값이 나올 수 있다(ex : process).
하지만 공부를 마치고 할 일도 결국 student가 하는 일인데 this 를 student 로 설정할 수 있다면 좋지 않을까? no, name, type 과 같은 다른 항목들도 접근할 수 있으니 여러모로 좋을 것이다.
study 메소드의 callback 함수 호출 구문을 변경한다.
Copy const student = {
no : 1,
name : "이상해씨",
type : "풀",
study : function(done){
console.log(this.name + " 학생이 공부를 합니다");
if(typeof done === 'function') {
//done();
done.call(this);
}
},
};
함수 호출을 Function.prototype.call()
로 해서 study()의 this (student)가 callback 함수에서도 this 가 될 수 있도록 설정하였다. callback 함수에서 this 를 출력하면 student가 나오는 것을 확인할 수 있다.
Arrow function 이용 시 주의사항
Javascript Arrow function은 this를 가지지 않습니다. 따라서 다음과 같이 코드를 작성할 경우 this는 window로 표시됩니다. 결론적으로 this 사용 시 일반 함수와 화살표 함수는 사용 방법이 달라질 수 있습니다.
Copy student.study(()=>{
console.log("공부 끝!");
});