본문 바로가기
카테고리 없음

자바스크립트에서의 this란?

by 계발자jessie 2023. 5. 2.
반응형

자바스크립트에서의 this는 객체를 가리키는 키워드이다. 즉, this는 객체라고 할 수 있고, 호출한 객체가 this가 된다. 만약 호출한 객체가 없을 경우 기본값은 window 객체이다. 

 

자바스크립트에서의 this

// 호출한 객체가 this가 되는 경우
let person = {
    fullname: '짐코딩',
    age: 20,
    printThis: function() {
        console.log(this); // {fullname: '짐코딩', age: 20, printThis: f}
        console.log(this === person); // true
    }
};
person.printThis(); // this => person

// 호출한 객체가 없는 경우 
let person = {
    fullname: '짐코딩',
    age: 20,
    printThis: function() {
        console.log(this); // Window {window: Window, self: ....
        console.log(this === person); // false
        console.log(this === window); // true
    }
};
let printThis = person.printThis;
printThis(); // this => window

똑같은 함수인 printThis()를 호출하는 경우이다. 이 때, person.printThis()를 통해 printThis()를 호출하는 경우 this 객체는 person이 된다. person을 통해 printThis를 호출했기 때문이다. 하지만 person.printThis를 printThis 변수에 담고 이를 호출할 경우 호출하는 객체는 default인 window가 된다.

 

예시

function printThis() {
    console.log(this); // default this => window
}
printThis();

let person1 = {
    name: '홍길동1',
    printThis: printThis
};
person1.printThis(); // this => person1

let person2 = {
    name: '홍길동2',
    printThis: printThis
};
person2.printThis(); // this => person2

let person3 = {
    name: '홍길동3',
    printThis: printThis
};
person3.printThis(); // this => person3

 

클릭 이벤트에서의 this

let btn = document.querySelector('button');
btn.addEventListener('click', function() {
    console.log(this); // button 요소
    console.log(this === btn); // true
});

document의 querySelector 요소를 통해 찾은 css선택자 button에 클릭 이벤트를 주고 클릭 사 this가 출력되게 했을 때 출력되는 this는 button 태그이다. document를 통해 호출된 객체이기 때문에 window가 출력될 것이라고 예상하지만 위와 같이 addEventListener를 통해 호출이 되는 경우 해당 이벤트가 발생되는 객체가 this가 되는 것을 확인할 수 있다.

 

bind를 사용해서 this를 내가 원하는 객체로 설정하기

// ES5 bind - this 설정
function printThis() {
    console.log(this); // default this => window
}
let person1 = {
    name: '홍길동'
};
let person2 = {
    name: '김길동'
};
printThis(); // this => window 
let printThis1 = printThis.bind(person1);
printThis1(); // this => person1
let printThis2 = printThis1.bind(person2);
printThis2(); // this => person1

위에서 this는 호출하는 객체가 되는 것을 알아보았다. 그런데 this를 변경하고 싶은 경우가 있을 수 있다. 그럴 때 사용하기 위해 나온 것이 바로 bind이다. printThis()를 통해 호출되는 this는 window이다. 여기서 이 함수에 bind를 사용해서 변경하고 싶은 객체를 넣어주면 printThis1 함수에서 처럼 해당 객체가 this로 변경되는 것을 볼 수 있다. 그런데 printThis2 함수의 경우 printThis1에 다시 bind함수를 사용해서 person2 객체를 넣어주었지만 여전히 this 객체는 person1인 것을 알 수 있다. 그 이유는 바로 bind는 원래의 함수에 한 번만 사용할 수 있기 때문이다. 

 

예시

let person = {
    name: '짐코딩',
    age: 20,
    hello: function() {
        console.log(this); // this => person
        setTimeout(function() {
            console.log(this); // this => window
            console.log(this.name);
            console.log(this.age);
        }, 1000);
    }
}
person.hello();

// bind를 사용해서 this 변경
let person = {
    name: '짐코딩',
    age: 20,
    hello: function() {
        console.log(this); // this => person
        setTimeout((function() {
            console.log(this); // this => person
            console.log(this.name);
            console.log(this.age);
        }).bind(this), 1000);
    }
}
person.hello();

// 좀 더 직관적으로 변경
let person = {
    name: '짐코딩',
    age: 20,
    hello: function() {
        function printHello() {
            console.log(this); // this => window
            console.log(this.name);
            console.log(this.age);
        }
        setTimeout(printHello.bind(this), 1000);
    }
}
person.hello();

setTimeout 에서 콜백함수에 this를 bind해주면 person 객체를 this로 사용할 수 있게 된다. 이를 좀 더 직관적으로 보기 편하게 변경하면 hello function 안에 printHello라는 함수를 선언하고 이를 this 로 bind 하게되면 똑같이 동작하게 된다. 

 

화살표함수에서의 this

// 화살표함수가 등장하기 전
let person = {
    name: '짐코딩',
    age: 20,
    hello: function() {
        let that = this;
        setTimeout(function() {
            console.log(that); // this => person
            console.log(that.name);
            console.log(that.age);
        }, 1000);
    }
}
person.hello();

// 회살표함수가 등장한 후
let person = {
    name: '짐코딩',
    age: 20,
    hello: function() {
        setTimeout(() => {
            console.log(this); // this => person
            console.log(this.name);
            console.log(this.age);
        }, 1000);
    }
}
person.hello();

// 전역 스코프가 화살표함수를 감싸는 경우
let person = {
    name: '짐코딩',
    printThis: () => {
        console.log(this); // this => window
    }
}

person.printThis();

화살표함수가 등장하기 전, hello 요소의 안에서 setTimeout 을 호출할 때에 this를 사용하고 싶은 경우 this를 that이라는 변수에 담고, 그것을 this처럼 활용하는 방식을 사용했다. 하지만 화살표함수가 등장한 후에는 변화가 일어났다. 화살표함수에서의 경우 화살표함수가 포함되어있는 스코프의 this 객체를 물려받는다. person.hello() 에서는 setTimeout 콜백함수가 포함되어있는 hello 스코프의 this를 물려받는다. 때문에 this는 person이 된다. person.printThis()의 경우 printThis 자체가 바로 화살표함수로 동작한다. printThis의 스코프는 전역이 되고, 따라서 여기서의 this는 window 객체가 된다.

 

strict 모드에서의 this

// 기본 모드에서의 this
function printThis() {
    console.log(this); // this => window 
}
printThis();

// strict 모드에서의 this
'use strict';
function printThis() {
    console.log(this); // this => undefined 
}
printThis();

기본 모드에서는 호출하는 객체가 없는 경우 기본값은 window객체가 되었다. 하지만 엄격모드인 strict 모드에서는 기본값이 undefined가 된다. 더욱 엄격하게 객체를 관리하는 것이다.

 

 

 

출처 : https://www.inflearn.com/course/lecture?courseSlug=%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C-%EB%82%A0%EA%B0%9C%EB%8B%AC%EA%B8%B0&unitId=115158&category=questionDetail 

 

학습 페이지

 

www.inflearn.com

 

반응형

댓글