JavaScript

[JavaScript] this

댕주 2024. 11. 10. 21:25

JavaScript의 this 키워드: 스코프에 따른 동작 방식

JavaScript에서 this함수가 호출되는 방식에 따라 가리키는 대상이 달라지는 동적 바인딩 키워드다. 상황에 따라 this 의 참조가 바뀌기 때문에 정확한 동작 방식을 이해하는 것이 좋다

 

1. 전역

  • 전역에서 사용될 때, this전역 객체를 참조한다.
  • 브라우저 환경에서는 window 객체, Node.js 환경에서는 global 객체를 가리킨다
console.log(this) // 브라우저에서는 window, Node.js에서는 global

 

2. 메서드

  • 객체의 메서드에서 this해당 메서드가 속한 객체를 참조한다
  • 즉, 메서드가 호출될 때만 this 는 해당 객체를 참조하므로, 호출 위치가 중요하다
const person = {
    name: "Alice",
    sayHello() {
        console.log(`Hello, ${this.name}`);
    }
};
person.sayHello(); // "Hello, Alice" - this는 person 객체를 참조

 

3. 함수

  • 일반 함수에서의 this 는 호출 방식에 따라 달라지며, 기본적으로 전역 객체를 가리킨다
  • use strict 모드에서는 undefined 가 된다 (▶하단 설명 참조)
function showThis() {
    console.log(this);
}
showThis(); // 전역 객체

"use strict":
function showThisStrict() {
    console.log(this)
}
showThisStrict(); // undefined

 

4. 생성자 함수

  • new 키워드를 사용해서 생성자 함수를 호출하면 this새롭게 생성되는 객체를 참조한다
  • 이때 this 는 새 인스턴스와 연결된다
function Person(name) {
    this.name = name;
}
const alice = new Person("Alice");
console.log(alice.name); // "Alice" - this 는 새로 생성된 alice 객체

 

5. 화살표 함수

  • 화살표 함수는 상위 스코프this 를 그대로 상속받는다
  • 일반 함수와 달리 this 바인딩이 고정되어 있으며, 호출 방식에 상관없이 this 가 변하지 않는다. (▶하단 설명 참조)
const person = {
    name: "Alice",
    sayHello: () => {
        console.log(this.name); // undefined - this는 전역 객체 참조
    }
};
person.sayHello();

 

6. 명시적 바인딩: call, apply, bind

  • callapply 메서드를 사용하면 함수 호출 시 this 를 특정 값으로 설정할 수 있다 (▶하단 설명 참조)
  • bind 메서드는 this 를 영구적으로 고정하는 새로운 함수를 반환한다
function greet() {
    console.log(`Hello, ${this.name}`);
}

const user = { name: "Alice" };
greet.call(user); // Hello, Alice
greet.apply(user); // Hello,Alice

const boundGreet = greet.bind(user);
boundGreet(); // Hello, Alice

 

상황 this 가 가리키는 대상
전역 문맥 전역 객체(window 또는 global)
객체의 메서드 메서드가 호출된 객체
일반 함수 기본적으로 전역 객체, 엄격 모드에서는 undefined
생성자 함수 새로 생성되는 객체
화살표 함수 상위 스코프의 this
call, apply, bind 지정한 객체

 


엄격 모드 ("use strict")란 무엇인가?

ES5부터 도입된 자바스크립트에서 더 엄격한 규칙을 적용하도록 하는 모드이다. 엄격 모드를 활성화하면 일반적인 코드에서 허용되는 몇 가지 관행을 제한하여, 더 안전하고 성능이 좋은 코드를 작성할 수 있다

  • 엄격 모드 활성화 방법: 코드 파일 전체나 함수 내부에 "use strict"; 를 추가한다.
"use strict";
// 또는 함수 내에서
function example() {
    "use strict";
    // 엄격 모드 적용
}
  • this 가 전역 객체를 참조하는 대신, 함수 내에서 undefined 로 설정된다.
  • 암묵적 전역 변수 생성을 금지한다
  • 같은 이름의 매개변수 사용을 금지한다
  • eval 함수의 사용을 제한하고, 변수 선언에 영향을 미치지 않는다

 

호출 방식에 상관없이 this 가 고정된다는 것은?

화살표 함수에서 this 는 고유의 this 를 가지지 않으며, 상위 스코프의 this 를 그대로 상속한다. 따라서 어떤 방식으로 호출하더라도 this 가 변하지 않고 고정된다는 의미이다.

 

예를 들어, 화살표 함수는 호출 위치나 호출 방법에 관계없이 정의될 당시의 스코프에서 this 를 가져온다

const person = {
  name: "Alice",
  greet: () => {
    console.log(this.name); // 상위 스코프의 `this`를 참조 (여기서는 전역 객체)
  }
};

person.greet(); // undefined - 화살표 함수는 호출 방식에 상관없이 전역 `this`를 사용

 

일반 함수에서는 호출 방식에 따라 this 가 달라지지만, 화살표 함수는 this 가 고정되므로 호출 문맥에 영향을 받지 않는다

 

명시적 바인딩이란 무엇인가?

명시적 바인딩this 를 특정 객체로 명확하게 설정할 수 있는 방법을 의미하며, JavaScript에서 제공하는 call, apply, bind 메서드를 통해 구현된다

  • call : 함수를 호출하면서 this 를 특정 객체로 설정한다. 인수는 하나씩 나열한다
function greet() {
  console.log(`Hello, ${this.name}`);
}

const user = { name: "Alice" };
greet.call(user); // Hello, Alice
  • apply : call 과 동일하지만, 인수를 배열 형태로 전달한다
greet.apply(user); // Hello, Alice
  • bind : this 가 특정 객체로 영구적으로 고정된 새 함수를 반환한다.
const boundGreet = greet.bind(user);
boundGreet(); // Hello, Alice

 

명시적 바인딩은 this 가 필요한 특정 객체를 참조하도록 강제로 설정할 때 유용하게 사용된다