본문 바로가기

FE/JS

JavaScript - this

this는 JavaScript에서 함수가 호출될 때 결정되는 특별한 키워드이다.

 

JavaScript에서 this함수가 어떻게 호출되었는지에 따라 바인딩된다.

선언 위치가 아닌 호출 시점에 따라 결정되므로, 예상과 다른 동작이 발생하기 쉽다.


1. 호출 방식에 따라 달라지는 this

const obj = {
  name: 'obj',
  logThis: function () {
    console.log(this.name);
  }
};

obj.logThis(); // 'obj'
const extracted = obj.logThis;
extracted(); // undefined
const wrapper = { name: 'wrapper', call: obj.logThis };
wrapper.call(); // 'wrapper'

 

2. 예상과 다른 this 동작

const temperatureLogger = {
  unit: "°C",
  values: [23, 25, 27],
  printTemperatures: function () {
    const result = this.values.map(function (val) {
      return val + this.unit;
    });
    console.log(result); // [NaN, NaN, NaN]
  },
};
temperatureLogger.printTemperatures();

map 내부 콜백이 일반 함수로 실행되어 this는 전역 객체(window)를 가리킨다.

 

3. 호출 방식별 this 예시

메서드 호출

const fruit = {
  name: "apple",
  getName: function () {
    console.log(this.name);
  },
};
fruit.getName(); // apple

 

함수 분리

const fn = fruit.getName;
fn(); // undefined

 

다른 객체에 재할당

const fruit2 = {
  name: "banana",
  getName: fruit.getName,
};
fruit2.getName(); // banana

 

중첩 함수

const book = {
  title: "JavaScript",
  printTitle: function () {
    console.log("outer:", this.title); // JavaScript
    function inner() {
      console.log("inner:", this); // Window
    }
    inner();
  },
};
book.printTitle();

 

4. this 고정 방법: bind / call / apply

bind

function printName() {
  console.log(this.name);
}
const fruit = { name: "apple" };
const boundFn = printName.bind(fruit);
boundFn(); // apple

bind()새로운 함수를 반환하며, 해당 함수가 호출될 때 this가 항상 지정한 객체를 참조하도록 만든다.

즉시 호출되지는 않고, 나중에 호출할 수 있도록 this가 '고정된' 버전을 반환한다.

❗ 화살표 함수에는 bind()를 사용해도 this가 바뀌지 않는다.


call / apply

call()apply()는 함수를 즉시 호출하면서 this를 특정 객체로 설정하고 싶을 때 사용한다.

 

이 둘의 차이는 인자를 전달하는 방식이다:

  • call(thisArg, arg1, arg2, ...) → 인자를 나열
  • apply(thisArg, [arg1, arg2, ...]) → 인자를 배열로 전달
❗ 화살표 함수는 call()이나 apply()를 사용해도 this를 변경할 수 없다.

예시 1

var obj = { a: "Custom" };
var a = "Global";
function whatsThis() {
  return this.a;
}
whatsThis();           // "Global"
whatsThis.call(obj);   // "Custom"
whatsThis.apply(obj);  // "Custom"

 

예시 2

function add(c, d) {
  return this.a + this.b + c + d;
}
var o = { a: 1, b: 3 };
add.call(o, 5, 7);        // 16
add.apply(o, [10, 20]);   // 34

 

⚠️ 비엄격 모드에서는 null이나 undefined를 넘기면 this는 전역 객체가 된다.
숫자나 문자열 같은 원시값은 해당 생성자 함수로 감싸진 객체로 변환된다.

function bar() {
  console.log(Object.prototype.toString.call(this));
}
bar.call(7);        // [object Number]
bar.call("foo");   // [object String]
bar.call(undefined);// [object global]

 

5. 화살표 함수에서의 this

화살표 함수는 자신만의 this를 가지지 않는다.

대신 선언된 위치의 상위 스코프에서 this를 가져온다.

이 특성 때문에 bind(), call(), apply()를 사용해도 화살표 함수의 this는 바뀌지 않는다.
즉, 화살표 함수에 this를 명시적으로 바인딩해도 효과가 없다는 점에 유의해야 한다.
function outer() {
  this.name = "outer";
  const inner = () => {
    console.log(this.name); // "outer"
  };
  inner();
}
outer();
const obj = {
  name: "arrow",
  show: () => {
    console.log(this.name);
  },
};
obj.show(); // undefined

const bound = obj.show.bind({ name: 'bound' });
bound(); // 여전히 undefined

 

6. 생성자 함수 vs 일반 함수 호출

var name = 'global';

function Func() {
  this.name = 'Func';
}

var a = Func();
console.log(name); // 'Func'
console.log(a);    // undefined

var b = new Func();
console.log(b.name); // 'Func'
  • new 없이 호출 → this는 전역 객체를 가리킴
  • new와 함께 호출 → 새 객체가 생성되고 this에 바인딩됨

 

7. 이벤트 리스너에서의 this

<button id="btn">Click</button>
<script>
  const button = document.getElementById("btn");

  button.addEventListener("click", function () {
    console.log(this); // <button>
  });

  button.addEventListener("click", () => {
    console.log(this); // window
  });
</script>
  • 일반 함수 → this는 이벤트를 발생시킨 요소를 가리킨다 (이 예시에선 <button>)
  • 화살표 함수 → this는 상위 스코프의 값을 그대로 참조하며, 일반적으로 window

💡 DOM 이벤트 처리기로 함수가 사용될 경우 this는 이벤트를 발생시킨 요소로 자동 설정된다.
하지만 addEventListener() 이외의 방법(예: element.onclick = ...)이나 구형 브라우저에서는 이러한 동작이 일관되지 않을 수 있다. 항상 명확한 동작을 원한다면 addEventListener() 사용이 권장된다.

 

8. 예제 해결 방법 정리

const temperatureLogger = {
  unit: "°C",
  values: [23, 25, 27],
  printTemperatures: function () {
    // 방법 1: bind 사용
    const result1 = this.values.map(function (val) {
      return val + this.unit;
    }.bind(this));

    // 방법 2: 화살표 함수 사용
    const result2 = this.values.map(val => val + this.unit);

    console.log(result1); // ["23°C", "25°C", "27°C"]
    console.log(result2); // ["23°C", "25°C", "27°C"]
  },
};

참고

'FE > JS' 카테고리의 다른 글

자바스크립트 - 클로저  (1) 2025.05.19
자바스크립트 실행 컨텍스트  (0) 2025.05.19
자바스크립트 호이스팅 정리  (1) 2025.05.18
null, undefined, undeclared, NaN  (1) 2025.05.17
JavaScript: var, let, const  (0) 2025.05.13