this가 어떤 값을 가지는지 각 상황을 가정하여 설명해주세요.의도: 각 상황에 따라 this의 변화를 이해하고 있는지 확인하기 위한 질문
나의 답안
this는 자바스크립트에서 함수가 호출되는 방식에 따라 값이 결정되는 특별한 키워드입니다.
즉,this는 함수의 선언 위치가 아니라 실행 시점에 동적으로 결정됩니다.
전역 범위에서
this는 일반적으로 전역 객체를 참조합니다.
브라우저 환경에서는 window 객체, Node.js 환경에서는 global 객체를 참조합니다.
일반 함수 호출에서는
this가 기본적으로 전역 객체를 참조합니다.
다만, use strict 모드에서는this가undefined가 됩니다.
메서드를 호출할 때,
this는 메서드를 가지고 있는 객체를 참조합니다.
생성자 함수에서의
this는 새로 생성된 빈 객체를 참조합니다.
화살표 함수는 렉시컬 컨텍스트에서
this를 결정합니다.
렉시컬 컨텍스트는 자바스크립트 코드가 작성된 물리적인 위치에 따라 변수와 함수의 스코프가 결정되는 방식입니다.
즉, 화살표 함수의this는 선언된 위치의 상위 스코프에서this를 가져옵니다.
이벤트 핸들러에서
this는 이벤트를 바인딩한 DOM 요소를 참조합니다.
이때, 일반 함수가 아닌 화살표 함수를 사용하면this는 상위 스코프를 참조합니다.
마지막으로, 클래스에서의
this는 생성된 인스턴스 객체를 참조합니다.
주어진 답안 (모범 답안)
this는 호출되는 상황마다 서로 다른 값을 참조하고 있어 혼동하기 쉬운 값입니다.
우선 일반 함수를 호출할 때는 전역 객체인
window를 뜻합니다.
그리고 객체의 메서드를 호출할 때에는 해당 객체를 의미합니다.
이어서 콜백 함수는 전달하는 곳은 상관이 없고, 함수가 실제로 호출되는 상황에 따라 달리집니다.
만약 호출하는 상황이 일반 함수라면 전역 객체를 가리킵니다.
마지막으로 화살표 함수는 생성된 함수의 스코프에 따라 달라집니다.
예를 들어 객체의 메서드에서 화살표 함수를 만들어서this를 호출했다면 생성된 함수의 스코프는 객체 스코프이므로 여기서this는 객체를 뜻하게 됩니다.
이러한
this의 특징 때문에call,apply,bind같은 것으로this를 고정시켜주기도 하지만, 저는 저 포함 동료분들의 혼선을 피하기 위해this의 사용을 좀 지양하는 편입니다.
this는 자바스크립트에서 함수가 호출되는 방식에 따라 값이 결정되는 특별한 키워드이다.
이 값은 함수의 실행 문맥(Execution Context)을 참조한다.
상황에 따라 다르게 동작하기 때문에 이해가 중요하다.
this의 동작 원리this의 값은 함수가 어떻게 호출되었는지에 따라 동적으로 결정된다.
즉, this는 함수의 선언 위치가 아니라 실행 시점에 결정된다.
this가 결정되는 방식thisthis는 일반적으로 전역 객체를 참조한다.window 객체global 객체console.log(this); // 브라우저: window, Node.js: {}함수 호출에서의 this
일반 함수 호출에서는 this가 기본적으로 전역 객체를 참조한다.
use strict 모드에서는 this가 undefined가 된다.
function globalFunction() {
console.log(this); // 브라우저: window, Node.js: global
}
globalFunction();
'use strict';
function strictFunction() {
console.log(this); // undefined
}
strictFunction();
메서드 호출에서의 this
메서드를 호출할 때, this는 메서드를 소유하는 객체를 참조한다.
const obj = {
name: 'Object',
method() {
console.log(this.name);
}
};
obj.method(); // "Object"
생성자 함수에서의 tihs
생성자 함수는 new 키워드와 함께 호출되며, this는 새로 생성된 빈 객체를 참조한다.
function Person(name) {
this.name = name;
}
const person = new Person("Alice");
console.log(person.name); // "Alice"
this를 명시적으로 설정하는 이유
자바스크립트에서는 call, apply, bind 메서드를 사용하여 this를 명시적으로 설정할 수 있다.
call과 apply: 함수를 호출하면서 this를 특정 값으로 설정한다.
call: 인수를 개별적으로 전달apply: 인수를 배열로 전달
function greet(greeting) {
console.log(`${greeting}, ${this.name}`);
}
const user = { name: "Alice" };
greet.call(user, "Hello"); // "Hello, Alice"
greet.apply(user, ["Hi"]); // "Hi, Alice"
bind: 새로운 함수를 반환하며, this를 영구적으로 설정한다.
const boundGreet = greet.bind(user);
boundGreet("Hey"); // "Hey, Alice"
화살표 함수에서의 this
화살표 함수는 렉시컬 컨텍스트에서 this를 결정한다.
즉, 화살표 함수의 this는 선언된 위치의 상위 스코프의 this를 사용한다.
const obj = {
name: "Object",
arrowMethod: () => {
console.log(this.name); // 화살표 함수의 this는 전역 객체 참조
},
regularMethod() {
console.log(this.name); // 일반 함수의 this는 obj 참조
}
};
obj.arrowMethod(); // undefined (strict mode) 또는 window.name
obj.regularMethod(); // "Object"
렉시컬 컨텍스트(Lexical Context)
렉시컬 컨텍스트는 자바스크립트 코드가 작성된 물리적인 위치에 따라 변수와 함수의 스코프가 결정되는 방식이다.
이 개념은 자바스크립트의 스코프 체인(Scope Chain) 및 클로저(Closure)와 밀접하게 관련되어 있으며, 특히 화살표 함수에서this가 동작하는 방식의 기초가 된다.
⭐ 렉시컬 컨텍스트의 핵심 개념
렉시컬 스코프(Lexical Scope)
렉시컬 스코프는 코드가 작성된 위치에 따라 변수와 함수의 유효 범위가 결정되는 것을 의미한다.
자바스크립트는 정적 스코핑(static scoping)을 사용하며, 실행 시점이 아니라 코드 작성 시점에 스코프가 결정된다.
function outer() {
const outerVar = "I am from outer";
function inner() {
console.log(outerVar); // outerVar를 inner에서 참조 가능
}
inner();
}
outer(); // "I am from outer"
inner 함수는 작성된 위치에 따라 바로 바깥의 스코프인 outer 함수의 변수를 참조할 수 있다.outerVar는 inner 함수 내부에서 사용할 수 있지만, 반대로는 불가능하다.렉시컬 컨텍스트와 실행 컨텍스트
렉시컬 컨텍스트는 코드가 작성된 물리적 구조를 기반으로 스코프 체인을 정의하는 반면, 실행 컨텍스트는 함수 호출 시 만들어지는 실행 환경을 나타낸다.
this와 같은 실행 정보를 포함한다.화살표 함수와 렉시컬 컨텍스트
화살표 함수는 this를 포함한 컨텍스트를 렉시컬하게 결정한다.
즉, 화살표 함수의 this는 선언된 위치의 상위 스코프에서 this를 가져온다.
const obj = {
name: "Alice",
regularFunction: function () {
console.log(this.name); // "Alice"
},
arrowFunction: () => {
console.log(this.name); // 상위 스코프의 this (전역 객체)
}
};
obj.regularFunction(); // "Alice"
obj.arrowFunction(); // undefined (strict 모드) 또는 window.name
this는 호출 시점에 결정된다.this는 선언된 위치에서 렉시컬하게 상속받는다.⭐ 렉시컬 컨텍스트의 특징
function outer() {
const outerVar = "Outer Variable";
function inner() {
console.log(outerVar); // 접근 가능
}
inner();
}
console.log(outerVar); // ReferenceError: outerVar is not definedfunction createCounter() {
let count = 0;
return function () {
count++;
return count;
};
}
const counter = createCounter();
console.log(counter()); // 1
console.log(counter()); // 2⭐ 렉시컬 컨텍스트와 this의 차이
렉시컬 컨텍스트는 스코프와 관련된 개념이고, this는 실행 컨텍스트에 따라 동적으로 설정되는 개념이다.
화살표 함수는 렉시컬 컨텍스트에서 this를 결정한다는 점에서 렉시컬 컨텍스트와 연결된다.
DOM 이벤트 핸들러에서의 this
이벤트 핸들러에서 this는 이벤트를 바인딩한 DOM 요소를 참조한다.
const button = document.querySelector("button");
button.addEventListener("click", function () {
console.log(this); // 클릭된 button 요소
});
화살표 함수를 사용하면 this는 상위 스코프를 참조한다.
button.addEventListener("click", () => {
console.log(this); // 전역 객체 (window)
});
클래스에서의 this
클래스에서의 this는 생성된 인스턴스 객체를 참조한다.
class Person {
constructor(name) {
this.name = name;
}
sayName() {
console.log(this.name);
}
}
const person = new Person("Alice");
person.sayName(); // "Alice"
객체 메서드 참조 분리
객체의 메서드를 변수에 할당하거나 다른 함수에 전달하면 this가 달라질 수 있다.
const obj = {
name: "Object",
method() {
console.log(this.name);
}
};
const detached = obj.method;
detached(); // undefined (전역 객체의 this)
해결 방법: bind를 사용하여 this를 고정한다.
const boundMethod = obj.method.bind(obj);
boundMethod(); // "Object"
화살표 함수와 this
화살표 함수는 렉시컬 스코프의 this를 사용하므로 객체에서 사용할 때 주의해야 한다.
const obj = {
name: "Object",
arrowMethod: () => {
console.log(this.name); // undefined
}
};
obj.arrowMethod();
이벤트 핸들러에서의 this
화살표 함수로 이벤트 핸들러를 정의하면 this가 의도와 다르게 전역 객체를 참조할 수 있다.
document.body.innerHTML = `
<button id="myButton">Click Me</button>
`;
const button = document.getElementById("myButton");
const obj = {
label: "Button Label",
handleClick: () => {
console.log(this.label); // 여기서의 this는 obj가 아님
},
};
button.addEventListener("click", obj.handleClick);
- 위 코드를 실행하면 버튼을 클릭했을 때
this.label이undefined로 출력된다.- 화살표 함수 내부의
this는 이벤트 핸들러를 등록한 객체(obj)가 아닌 전역 객체(window또는undefined(strict mode))를 참조하기 때문이다.
해결 방법
1) 일반 함수로 this 바인딩
const obj = {
label: "Button Label",
handleClick: function () {
console.log(this.label); // this는 obj를 참조
},
};
button.addEventListener("click", obj.handleClick);
2) bind로 명시적으로 this 설정
const obj = {
label: "Button Label",
handleClick: function () {
console.log(this.label); // this는 obj를 참조
},
};
button.addEventListener("click", obj.handleClick.bind(obj));
3) 화살표 함수 내부에서 명시적으로 this를 사용하지 않기
const obj = {
label: "Button Label",
init: function () {
const self = this; // obj를 참조하는 self
button.addEventListener("click", () => {
console.log(self.label); // 화살표 함수 안에서도 self를 사용
});
},
};
obj.init();
this는 함수 호출 방식에 따라 값이 동적으로 결정된다.this를 사용하며, bind, call, apply를 통해 명시적으로 설정할 수 있다.this의 동작을 정확히 이해하고, 상황에 맞는 패턴과 메서드(bind, 화살표 함수 등)를 사용해 예기치 않은 동작을 방지하는 것이 중요하다.