HomeAboutMeBlogGuest
© 2025 Sejin Cha. All rights reserved.
Built with Next.js, deployed on Vercel
🌳
말하면서 배워요 스터디
/
📒
this
📒

this

생성일
Sep 7, 2022 06:56 AM
태그
대주제
JS
상태
Done
소주제
this
유형
JS
수경
수경
인수
인수
준혁
창민
창민
this 질문 리스트인수 this수경 this창민 this

this 질문 리스트

⭐
해당하는 질문들을 대답할 수 있도록, 본인이 공부한 흐름에 맞게 정리하여 올려주세요.
자바스크립트에서 this는 다른 언어와 어떤 차이점이 있나요?
호출 방식에 따라 어떤 값을 가질 수 있나요?
call/apply/bind의 역할은 무엇인가요?
화살표 함수를 통한 정적 바인딩이 좋은 방법인가요? 상황별로 다르다면, 어떤 상황에서 화살표 함수를 통해 this를 정적 바인딩 하는 것이 좋고, 어떤 상황에서 좋지 않을까요?

인수 this

1. this란

  • this는 실행컨텍스트가 생성될 때, this의 값이 결정된다.
  • 실행컨텍스트는 함수 호출 시에 결정된다.
    • this는 함수 호출 시에 결정된다.
    • this는 함수 호출 방법에 따라 다른 값을 가진다.

2. 호출 상황에 따라 달라지는 this 값

[전역공간에서의 this]
[메서드 호출 시의 this]
[함수 자체 호출 시의 this]
[생성자 함수에서의 this]
[콜백함수 내부에서의 this]

3. 명시적 this 바인딩

[call, apply 메서드]
[bind 메서드]
[고차함수에서의 this 바인딩]

수경 this

함수 실행에서의 this
함수 실행에서의 this는 전역 객체다
전역 객체는 실행하는 환경마다 다릅니다. 웹 브라우저에서는 window 객체가 전역 객체가 된다.
function sum(a, b) { console.log(this === window); // => true this.myNumber = 20; // 전역 객체에 'myNumber'라는 속성을 추가 return a + b; } // sum()은 함수 호출이다. // sum()에서의 this는 전역 객체다. (window) sum(15, 16); // => 31 window.myNumber; // => 20
또한 this가 함수 스코프 밖(최상단: 전역 실행 문맥)에서 사용되었을 경우, 여기서의 this 역시 전역 객체를 참조하게 된다.
console.log(this === window); // => true this.myString = 'Hello World!'; console.log(window.myString); // => 'Hello World!'
 
엄격 모드 함수 실행에서의 this
엄격 모드에서 함수 실행에서의 this는 undefined이다.
자바스크립트의 엄격 모드는 ES5에서 등장하였으며, 코드 안정성과 더 나은 오류 검증을 제공하기 위해 등장하였다. use strict 를 사용하여 엄격 모드를 적용시킬 수 있다.
function multiply(a, b) { 'use strict'; // 엄격 모드 console.log(this === undefined); // => true return a * b; } // multiply() 함수는 엄격 모드로 실행됨 // multiply()에서의 this는 undefined multiply(2, 5); // => 10
엄격 모드에서는 this의 값이 window 전역 객체를 참조하지 않고 undefined 로 만든다.
 
엄격 모드는 현재 스코프 뿐만 아니라 내부 스코프에서도 적용됩니다.
function execute() { 'use strict'; // 엄격 모드 function concat(str1, str2) { // 이곳에서도 마찬가지로 엄격 모드 console.log(this === undefined); // => true return str1 + str2; } // concat() 함수는 엄격 모드 // concat() 함수 안에서의 this는 undefined concat('Hello', ' World!'); // => "Hello World!" } execute();
내부 함수에서의 this를 사용할 때
내부 함수의 문맥은 외부 함수의 문맥에 의존하는 것이 아니라 오직 실행 환경에 좌우된다.
var numbers = { numberA: 5, numberB: 10, sum: function() { console.log(this === numbers); // => true function calculate() { // this는 window, 엄격 모드였으면 undefined console.log(this === numbers); // => false return this.numberA + this.numberB; } return calculate(); } }; numbers.sum(); // NaN, 엄격 모드였으면 TypeError
numbers.sum()은 객체 내에 있는 메소드를 실행하는 것이다. 따라서 this는 numbers 를 가리킨다.
하지만 calculate() 는 메소드 실행이 아닌 함수 실행이다. 이 함수에서의 this는 window 를 가리킨다.(엄격모드라면 undfined)
 
이 문제의 해결책 중 하나로 .call 메소드를 사용하는 방법이 있다.
var numbers = { numberA: 5, numberB: 10, sum: function() { console.log(this === numbers); // => true function calculate() { console.log(this === numbers); // => true return this.numberA + this.numberB; } // 문맥을 수정하기 위해 .call() 메소드를 적용 return calculate.call(this); } }; numbers.sum(); // => 15
 
메소드 실행에서의 this
함수 실행과 메소드 실행은 서로 다르다. 가장 큰 차이점은 메소드 실행은 속성 접근자를 사용하여 호출한다.
this는 메소드 실행에서 메소드를 소유하고 있는 객체이다.
var myDog = Object.create({ sayName: function() { console.log(this === myDog); // => true return this.name; } }); myDog.name = 'Milo'; // 메소드 실행. 여기서의 this는 myDog. myDog.sayName(); // => 'Milo'
 
ES6의 class 예약어에서의 this는 인스턴스 자신을 가리킨다.
class Planet { constructor(name) { this.name = name; } getName() { console.log(this === earth); // => true return this.name; } } var earth = new Planet('Earth'); // 메소드 실행. 여기서의 this는 earth. earth.getName(); // => 'Earth'
 
생성자 함수에서의 this
생성자 실행에서의 this는 새롭게 만들어진 객체이다.
function Foo () { console.log(this instanceof Foo); // => true this.property = 'Default Value'; } // 생성자 실행 var fooInstance = new Foo(); fooInstance.property; // => 'Default Value'
 
여기서 잠깐, 만약 new를 사용하지 않는다면 함수 실행이 되므로 this는 window객체를 가리키게 된다.
function Vehicle(type, wheelsCount) { this.type = type; this.wheelsCount = wheelsCount; return this; } // Function invocation var car = Vehicle('Car', 4); car.type; // => 'Car' car.wheelsCount // => 4 car === window // => true
 
call(), apply()와 bind()
[ call과 apply]
간접 실행인 .call()과 .apply() 메소드에서는 첫 번째 매개 변수로 this를 받는다.
두 메서드는 넘겨받는 인자의 형식만 다를 뿐, this를 특정 객체에 바인딩하여 함수를 호출하는 역할을 한다.
call과 apply의 가장 큰 차이점은 call메서드는 인수를 그대로 넘길 수 있지만 apply메서드는 함수에 전달할 인자들을 배열 형태로 전달해야한다는 것이다.
 
[bind]
비인딩 함수는 일반 함수에 .bind() 메서드가 적용된 것을 의미한다. bind 메서드의 첫 번째 인자로는 바인딩 함수에 적용할 this를 받는다. 그리고 함수를 호출하는 것이 아니라 새로운 함수를 반환한다.
function multiply(number) { 'use strict'; return this * number; } // 문맥을 지정해서 바인딩 함수를 생성 var double = multiply.bind(2); // 바인딩 함수를 실행 double(3); // => 6 double(10); // => 20
 
화살표 함수에서의 this
화살표 함수는 함수가 어떻게 호출되었는지에 따라 this에 바인딩할 객체가 동적으로 결정된다. 화살표 함수의 this 언제나 상위 스코프의 this를 가리킨다
class Point { constructor(x, y) { this.x = x; this.y = y; } log() { console.log(this === myPoint); // => true setTimeout(()=> { console.log(this === myPoint); // => true console.log(this.x + ':' + this.y); // => '95:165' }, 1000); } } var myPoint = new Point(95, 165); myPoint.log();
 
[자주하는 실수] - 화살표 함수를 사용해서는 안되는 경우
  1. prototype
function Period (hours, minutes) { this.hours = hours; this.minutes = minutes; } Period.prototype.format = () => { console.log(this === window); // => true return this.hours + ' hours and ' + this.minutes + ' minutes'; }; var walkPeriod = new Period(2, 30); walkPeriod.format(); // => 'undefined hours and undefined minutes'
format은 화살표 함수고, 전역에 정의 되었기 때문에 여기서의 this는 상위 컨텍스트인 전역 객체 window를 가리키게 된다.
 
  1. 메소드
// Bad const person = { name: 'Lee', }; Object.prototype.sayHi = () => console.log(`Hi ${this.name}`); person.sayHi(); // Hi undefined
 
  1. 생성자 함수
const Foo = () => {}; // 화살표 함수는 prototype 프로퍼티가 없다 console.log(Foo.hasOwnProperty('prototype')); // false const foo = new Foo(); // TypeError: Foo is not a constructor
화살표 함수는 생성자 함수가 가지고 있어야 할 prototype 프로퍼티가 없다.
 
  1. addEventListener 함수의 콜백 함수
// Bad var button = document.getElementById('myButton'); button.addEventListener('click', () => { console.log(this === window); // => true this.innerHTML = 'Clicked button'; }); button.addEventListener('click', function(){ console.log(this); // button 객체에 바인딩 됨 this.innerHTML = 'Clicked button'; });
addEventListener 함수의 콜백 함수를 화살표 함수로 정의하면 this가 상위 컨택스트인 전역 객체 window를 가리킨다. 일반 함수를 addEventListener() 함수의 콜백으로 넘긴 경우 this는 event.currentTarget 프로퍼티와 동일한 값을 가진다.

창민 this

자바스크립트에서 this는 다른 언어와 어떤 차이점이 있나요?
답변
함수가 호출되는 방식에 따라 this에 바인딩되는 값이 동적으로 결정된다
호출 방식에 따라 어떤 값을 가질 수 있나요?
답변
일반 함수 ⇒ 전역 객체
생성자 함수 ⇒ 함수가 생성할 인스턴스
메서드 ⇒ 메서드를 호출한 객체
call/apply/bind 메서드에 의한 간접 호출 ⇒ 첫 번째 인수로 전달한 특정 객체
call/apply/bind 의 역할은 무엇인가요?
답변
call apply 는 첫 번째 인수로 전달한 특정 객체를 this에 바인딩하고 함수를 호출한다
bind 또한 바인딩할 객체를 전달하지만 앞서 말한 두 가지와 다른 점은 호출을 하지 않는다
화살표 함수를 통한 정적 바인딩이 좋은 방법인가요? 상황별로 다르다면, 어떤 상황에서 화살표 함수를 통해 this를 정적 바인딩 하는 것이 좋고, 어떤 상황에서 좋지 않을까요?
답변
메서드로 화살표 함수를 사용하면 상위 스코프의 this가 바인딩되기 때문에 유의해서 사용해야 한다