본문 바로가기
자바스크립트 (JavaScript)/이론

[ 함수 ] this

by Hwanii_ 2023. 12. 10.
728x90
//  this 키워드
//  일반 함수의 this 키워드는 호출 위치에서 정의 된다.
//  화살표 함수의 this 키워드는 자신이 선언된 함수 (렉시컬) 범위에서 정의 된다.
//  렉시컬 == Lexical 이란 ?
//  함수가 동작할 수 있는 유효한 범위.

const user = {
    firstName: 'hwanii',
    lastName: 'kim',
    age: 96,
    getFullName: function () {
        return `${this.firstName} ${this.lastName}`
    }
}

console.log(user.getFullName()) //  hwanii kim

//  즉, user 객체 내부에서 사용된 this 키워드는 user 객체 자신을 의미한다.
//  this.firstName == user.firstName 이다.

const user2 = {
    firstName: 'test',
    lastName: 'lee',
    age: 28,
    getFullName: () => {    //  화살표 함수가 선언된 부분
        return `${this.firstName} ${this.lastName}`
    }
}

console.log(user2.getFullName())    //  undefined undefined

//  일반 함수와 화살표 함수를 사용 했을 때의 결과가 다르다.

//  화살표 함수는 일반 함수와 다르게 화살표 함수가 선언된 부분을 기준으로 this가 정의 된다.
//  이 말을 쉽게 다시 풀어서 말하자면, 화살표 함수가 선언된 내용을 감싸고 있는,
//  외부의 또 다른 함수를 기준으로 해서 this가 정의된다는 것이다.

//  하지만 위의 경우는 화살표 함수를 감싸는 외부의 다른 함수가 존재 하지 않기 때문에,
//  undefined가 출력 되는 것이다.
//  그래서 아래서 화살표 함수를 감싸는 새로운 함수를 만들어 보자.

function user3() {

    this.firstName = 'action'
    this.lastName = 'han'

    //  user 함수의 return 값으로는 변수에 따로 할당 되지 않은 객체 데이터 자체를 반환 하도록 작성.
    return {
        firstName: 'calm',
        lastName: 'park',
        age: 6,
        getFullName: () => {
            return `${this.firstName} ${this.lastName}`	
        }
    }
}

console.log(user3().getFullName())	//	action han

//  테스트

function user4() {

    // this.firstName = 'aaaaaaaaaa'
    // this.lastName = 'bbbbbbbbbb'

    const testObj = {
        firstName: 'calm',
        lastName: 'park',
        age: 6,
        getFullName: () => {
            return `${this.firstName} ${this.lastName}`
        }
    }
    return testObj
}

console.log(user4().getFullName())	//	action han

//  이렇게 하면, user4() 함수 내부에서 this.firstName이랑 this.lastName이 주석 처리 되서,
//  undefined가 출력 된다고 생각 했는데,
//  실제로는 user3() 함수 내부에 있는 this.firstName이랑 this.lastName을 참조 해서,
//  결과가 action han 이 되었다.
//  이 개념은 다시 봐야할듯 .. 스코프 개념인듯.

//  [ 참고 ]

//  위의 객체 데이터의 firstName, lastName 등은 속성 == 프로퍼티 라고 한다.
//  그런데, getFullName은 값으로 함수 데이터를 갖는데,
//  이렇게 함수 데이터를 값으로 갖는 속성 (프로퍼티) 은 다르게 메서드 == method 라고 부른다.
//  따라서, 위의 객체 데이터는 속성 == 프로퍼티 == 멤버변수 와 메서드를 같이 가지는 객체 데이터 이고,
//  이 모든것을 아울러서 말할 때, 멤버 라고 부르기도 한다.

//  예제

const timer = { //  객체 데이터 할당.
    title: 'TIMER !',
    timeout: function () {  //  timeout은 함수 데이터를 값으로 갖으므로, 메서드 == method
        console.log(this.title)
    },
    // timeout() {  //  위의 표현 방법과 동일한 표기 방법 이다. (ES6 에서 도입된 축약 표기 방법)
    //     console.log(this.title)
    // }
}
timer.timeout() //  TIMER ! (일반 함수로 표현 했기 때문에, this 키워드의 스코프는 내부)

//  예제 2

const timer2 = {
    title: 'TIMER 2222222222 !',
    timeout() { //  일반 함수를 사용한 상황. (축약 표기법)
        console.log(this.title) 
        setTimeout(function () {   
            console.log(this.title) 
        }, 1000)    
    }   
}   

timer2.timeout()    //  undefined

 

timeout() 함수 내부에서의 this는 timer2 를 참조 한다.
하지만, setTimeout 이라는 함수에서,
콜백 함수로 일반 함수를 작성 하면 어떻게 될까 ?
일반 함수에서의 this는 호출 위치에서 정의된다고 했다.
그렇다는것은 여기서의 일반 함수 (콜백) 는 setTimeout 함수 내부 어딘가에서 호출 된다.
setTimeout() 함수 내부에서 일반 함수가 사용 되었기 때문에, 당연한 말이다.
그런데 우리는 setTimeout 함수의 내부를 자세히 알지 못한다.
어쨌든, 모르는 어떤 함수 내부에서 title 이라는 속성을 조회하게 되는 것이다.
따라서, 위의 상황에서의 this.title은 undefined가 출력 되게 된다.
그래서 이런 경우에는 setTimeout의 콜백 함수로 사용 되는 함수를,
일반 함수가 아니라, 화살표 함수로 작성 하기 적합 하다.
왜냐하면 화살표 함수는 해당 함수가 선언된 범위 영역에서 정의 된다고 했으니까,
setTimeout 이라는 함수 내부가 아니라,
이 화살표 함수를 감싸고 있는 timeout() 이라는 함수가 가지고 있는 this 키워드는,
timer2라는 객체 데이터를 가리키기 때문에, 결국 화살표 함수 내부의 this는 timer2를 참조 하게 된다.

 

반응형

'자바스크립트 (JavaScript) > 이론' 카테고리의 다른 글

[ 함수 ] 호출 스케줄링  (0) 2023.12.10
[ 함수 ] 재귀 (Recursive)  (0) 2023.12.10
[ 함수 ] 콜백 (Callback)  (1) 2023.12.09
[ 함수 ] 즉시실행함수 (IIFE)  (0) 2023.11.06
[ 함수 ] 화살표 함수  (2) 2023.11.06