this

함수와 this의 활용에 대해서 살펴본다.

this arguments

일반적으로 this는 현재 함수가 실행중인 객체 자신을 지칭한다. 배운다. 좀 더 의미를 명확하게 하기 위해 주인공이라는 표현을 사용하도록 하겠다.

객체의 this와 call()

const student = {
    no : 1,
    name : "피카츄",
    korean : 50,
    english : 60,
    math : 70
};

학생 객체가 있다(시각적 편의를 위해 생성자 함수를 쓰지 않았다).

객체에는 번호(no), 이름(name), 국어점수(korean), 영어점수(english), 수학점수(math)를 저장할 수 있는 변수가 존재한다. 자바스크립트는 기본적으로 접근 제한이 존재하지 않으므로 각각의 변수에 대한 setter와 getter 메소드를 생성할 필요가 없다.

따라서 합계나 평균을 알고 싶다면 다음과 같은 코드를 작성해야 할 것이다.

console.log("총점 : " + (student.korean + student.english + student.math) + "점");

backtrick 출력 구문을 사용하면 덧셈 정도는 없앨 수 있다

console.log(`총점 : ${student.korean + student.english + student.math}점`);

이 경우 객체에 메소드를 추가하면 가독성과 효율성이 좋아진다.

const student = {
    no : 1,
    name : "피카츄",
    korean : 50,
    english : 60,
    math : 70,
    //합계를 구하는 함수 추
    total : function(){
        return korean + english + math;
    },
};

작성한 뒤 합계를 구하면 오류가 발생한다.

console.log(`총점 : ${student.total()}점`);
//ReferenceError : korean is not defined

메소드 내부에 korean이 정의되지 않았다는 뜻이며, this 키워드를 추가하면 주인공의 정보임을 명시하면 오류 없이 출력된다.

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 함수를 부를 때 다음과 같이 코드를 작성한다.

student.total()

이 코드는 Function.prototype.call 함수를 사용하여 다음과 같이 표현할 수 있다.

student.total.call(student);
Function.prototype.call() reference

따라서 다음과 같은 출력 구문도 정상 작동한다.

console.log(`총점 : ${student.total.call(student)}점`);

두 방식에 대해 한글로 해석을 달아보면 다음과 같다.

//[1] student의 total 함수를 실행한  반환값을 가져와라!
student.total()

//[2] 주인공을 student로 설정하고 student의 total 함수를 실행한 뒤 반환값을 가져와라!
student.total.call(student)

결과적으로는 동일한 실행 결과가 나온다. 하지만 [2] 방식은 주인공을 다르게 설정할 수 있다.

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 메소드를 추가한다.

const student = {
    no : 1,
    name : "이상해씨",
    type : "풀",
    study : function(){
        console.log(this.name + " 학생이 공부를 합니다");
    },
};

공부가 끝나면 연속적으로 실행할 작업을 지정하기 위해 매개변수로 함수를 받아서 실행하도록 코드를 추가한다. typeof를 이용한 타입 검사를 실시하였다.

const student = {
    no : 1,
    name : "이상해씨",
    type : "풀",
    study : function(done){
        console.log(this.name + " 학생이 공부를 합니다");

        if(typeof done === 'function') {
            done();
        }
    },
};

위와 같이 구성한 경우 공부만 시키거나 공부 후 해야할 일을 콜백 함수로 알려주면서 실행할 수 있다.

공부만 하도록 시키는 경우

student.study();

공부 후 해야 할 일을 알려주는 경우

student.study(function(){ 
    console.log("공부 끝!"); 
});

실행하면 다음과 같이 결과가 나온다.

이상해씨 학생이 공부를 합니다
공부 끝!

그렇다면 this에 대해서 알아보고 있는 현 상황에서 study에서의 this와 콜백 함수에서의 this는 어떤 대상을 가리킬까?

출력해보면 study() 에서는 student 객체가, callback 함수에서는 window 객체가 출력된다. window는 웹 브라우저의 root 객체일 뿐 다른 환경이라면 다른 값이 나올 수 있다(ex : process).

하지만 공부를 마치고 할 일도 결국 student가 하는 일인데 thisstudent로 설정할 수 있다면 좋지 않을까? no, name, type과 같은 다른 항목들도 접근할 수 있으니 여러모로 좋을 것이다.

study 메소드의 callback 함수 호출 구문을 변경한다.

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 이용 시 주의사항

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions

Javascript Arrow function은 this를 가지지 않습니다. 따라서 다음과 같이 코드를 작성할 경우 this는 window로 표시됩니다. 결론적으로 this 사용 시 일반 함수와 화살표 함수는 사용 방법이 달라질 수 있습니다.

student.study(()=>{ 
    console.log("공부 끝!"); 
});

Last updated