JavaScript의 “this” 키워드는 코드가 실행되고 있는 현재 객체 또는 컨텍스트에 대한 참조입니다. 이 키워드는 특정 인스턴스에 특정한 속성 및 메서드에 대한 액세스를 제공하므로 JavaScript를 사용한 객체 지향 프로그래밍의 필수 요소입니다. 자바스크립트에서 “이”의 실제 사용은 변수를 타겟팅하고, 이벤트 핸들러를 정의하고, 다양한 객체에서 작동하는 함수를 생성하는 데 이 기능을 활용하는 것을 포함합니다.

다양한 프로그래밍 언어에서 ‘this’의 일반적인 사용법에 대해 궁금해하는 프로그래머를 위해 다양한 맥락에서 ‘this’의 의미를 자세히 살펴보는 유익한 글을 소개합니다. 이 글은 오해를 바로잡고 부적절한 ‘이것’의 활용과 관련된 잠재적 함정을 강조하여 궁극적으로 효율적인 코딩 관행을 촉진하는 것을 목표로 합니다.

“this” 글로벌 범위 내부

글로벌 범위와 관련하여 ‘window’ 객체를 검색하는 것은 객체가 함수의 경계 너머에 존재할 때 달성할 수 있습니다. “글로벌 컨텍스트”라는 용어는 해당 객체가 함수의 범위 내에 국한되어서는 안 된다는 것을 의미합니다.

 if(true) {
  console.log(this) // returns window object
}

let i = 2
while(i < 10) {
  console.log(this) // returns window object till i === 9
  i++
}

앞서 언급한 코드를 실행하면 theWindowObject가 반환됩니다.

“this” 함수(메서드) 내부

“this”라는 용어는 함수 표현식의 컨텍스트 내에서 객체의 신원을 가정합니다. 반대로, 분리된 엔티티로 활용될 때는 창 창을 의미합니다. 더 자세히 설명하기 위해 몇 가지 사례를 살펴보겠습니다.

앞서 언급한 인스턴스에서는 sayName 함수가 대상 엔티티의 본질적인 구성 요소, 보다 구체적으로는 해당 엔티티와 관련된 속성 또는 속성으로 사용됩니다. 좀 더 자세히 설명하자면, sayName 함수가 me 객체의 범위 내에 캡슐화되면 해당 객체와 독점적으로 관련된 방법론적 접근 방식의 상태를 가정합니다. 따라서 이 특정 함수에 대한 참조는 해당 특정 객체를 명시적으로 식별하고 지정해야 합니다.

  
function sayName() {
  return `My name is ${this.name}`
}

const me = {
  name: "Kingsley",
  sayName: sayName
}

console.log(me.sayName()) // My name is Kingsley

이 문장은 `Me` 객체의 범위 내에서 `sayName()`을 호출하면 `me.name`과 동등한 신원이 생성된다는 것을 암시합니다.

자바스크립트 함수 내에서 ‘이’의 개념은 호출 시점에 함수의 왼쪽에 연결된 값 또는 객체를 가리키는 것으로 이해할 수 있습니다. 따라서 다양한 객체에서 sayName 함수를 활용하면 각 인스턴스마다 문맥과 관련된 ‘this’가 어떻게 변하는지를 확인할 수 있습니다.

이 글도 확인해 보세요:  슬랙에서 나만의 사용자 지정 슬래시 명령 만들기

실제로 격리된 함수 내에서 “this” 키워드를 사용하면 필연적으로 창 객체가 반환된다는 점에 유의할 필요가 있습니다. 이러한 함수는 기본적으로 기본적으로 창 객체와 연관되어 있기 때문에 이러한 현상이 발생합니다.

 function talk() {
  return this
}

talk() // returns the window object

객체에서 `talk()` 메서드를 호출하는 것은 `window.talk()` 함수를 호출하는 것과 동일하며, 메서드의 왼쪽에 배치된 모든 표현식은 메서드의 컨텍스트 내에서 `this` 키워드에 암시적으로 할당됩니다.

덧붙여, 자바스크립트 엄격 모드의 컨텍스트에서 함수 내에서 ‘this’ 키워드가 어떻게 작동하는지에 대해 알아두는 것이 중요합니다. 특히 이러한 환경에서는 ‘this’ 키워드가 원하지 않는 결과를 산출하거나 정의되지 않은 값을 반환할 수 있습니다. 또한 개발자는 React와 같은 특정 사용자 인터페이스 라이브러리가 엄격 모드를 사용할 수 있으므로 사용과 관련된 잠재적 결과를 신중하게 고려해야 한다는 점을 명심해야 합니다.

함수.bind()로 “this” 사용

특정 경우에는 함수를 객체 내의 메서드로 통합하는 것이 가능하지 않을 수 있습니다(이전 세그먼트에서 설명한 것처럼).

특정 상황에서는 해당 객체가 내 소유가 아니라 라이브러리와 같은 공유 리소스에서 빌려온 것일 수 있습니다. 또한 객체가 한번 생성되면 변경할 수 없는 불변 유형인 경우 객체에 직접 수정을 실행하는 것은 불가능할 수 있습니다. 그러나 함수 실행을 관련 객체에서 분리하기 위해 Function.bind() 메서드를 활용하면 원하는 결과를 얻을 수 있습니다.

제공된 코드 스니펫은 `sayName` 함수가 `me` 객체의 속성이 아니지만 `bind()` 함수를 활용하여 이 객체에 바인딩할 수 있는 인스턴스를 보여줍니다.

 function sayName() {
  return `My name is ${this.name}`
}

const me = {
  name: "Kingsley"
}

const meTalk = sayName.bind(me)

meTalk() // My name is Kingsley

함수를 호출할 때 `bind()` 메서드에 제공된 값은 해당 함수 호출의 매개변수로 사용됩니다.

간단히 말해서, `bind()` 메서드는 모든 함수에 적용될 수 있으며 객체라는 새로운 컨텍스트를 제공하는 데 활용될 수 있습니다. 이 새로 도입된 컨텍스트는 해당 함수 내에서 `this` 키워드의 의미를 대체합니다.

“this” 사용 With Function.call()

질문을 좀 더 정제된 방식으로 바꿔도 될까요? 다음은 한 가지 가능한 표현입니다: “완전히 새로운 함수 객체를 만들지 않고도 바인딩된 함수를 호출할 수 있는 방법이 있나요? 그렇다면 이 메커니즘을 무엇이라고 부르며 어떻게 작동하나요?

 function sayName() {
  return `My name is ${this.name}`
}

const me = {
  name: "Kingsley"
}

sayName.call(me) // My name is Kingsley

`call()` 메서드를 사용하면 나중에 호출할 수 있는 대체 함수를 생성하지 않고 함수를 직접 실행하게 됩니다.

이 글도 확인해 보세요:  Vite 시작하기: 최고의 빌드 툴

인수가 필요한 함수를 호출할 때 `call()` 메서드를 사용하여 해당 매개변수를 전달할 수 있습니다. 예를 들어, 다음 그림에서는 언어 코드를 `sayName()` 함수에 전송하여 다양한 통신의 조건부 검색에 활용할 수 있도록 하고 있습니다:

 function sayName(lang) {
  if (lang === "en") {
    return `My name is ${this.name}`
  } else if (lang === "it") {
    return `Io sono ${this.name}`
  }
}

const me = {
  name: "Kingsley"
}

sayName.call(me, 'en') // My name is Kingsley
sayName.call(me, 'it') // Io sono Kingsley

`call()` 메서드를 사용할 때 원하는 매개변수 또는 일련의 매개변수를 함수에 보조 인수로 전달할 수 있습니다. 또한 이 컨텍스트 내에서 광범위한 매개변수 배열이 허용되고 허용됩니다.

`apply()` 메서드는 `call()` 및 `bind()`와 유사하지만, 한 가지 주목할 만한 차이점이 있습니다. call()`을 사용할 때는 쉼표로 구분된 시퀀스를 통해 여러 인수를 전달하는 반면, `apply()`를 사용할 때는 동일한 요소를 배열 구조 내에 포함합니다.

간단히 말해서, 각 메서드인 bind(), call(), apply()를 사용하면 완전히 별개의 엔티티를 사용하여 함수를 호출할 수 있지만 그 사이에 어떤 형태의 연결도 필요하지 않습니다(즉, 함수가 객체의 속성이나 메서드가 아닌 경우).

“this” 생성자 함수 내부

“new” 키워드를 사용하여 함수를 호출하면 지정된 클래스의 인스턴스가 생성되고 그 결과로 반환됩니다.

 function person(name){
  this.name = name
}

const me = new person("Kingsley")
const her = new person("Sarah")
const him = new person("Jake")

me.name // Kingsley
her.name // Sarah
him.name // Jake

앞서 언급한 코드는 단일 기능 엔티티를 통해 세 개의 서로 다른 엔티티를 인스턴스화하는 예시입니다. 본질적으로, ‘new’ 키워드를 사용하면 지정된 함수 내에서 ‘this’로 표시되는 현재 컨텍스트의 참조 표현과 구축 중인 객체 간에 내재적 연관성이 설정됩니다.

“this” 콜백 함수 내부

콜백 함수는 실행 패러다임에서 표준 함수와 다릅니다. 콜백 함수는 다른 함수에 인수로 전달되어 주 함수가 완료된 직후에 호출되는 함수입니다.

콜백 함수의 범위 내에서 활용될 때 “이”는 종종 전체 프로그램 본문에서 의미하는 것과는 다른 고유한 컨텍스트를 나타냅니다.

 function person(name){
  this.name = name
  setTimeout(function() {
    console.log(this)
  }, 1000)
}

const me = new person("Kingsley") // returns the window object

사람 구성을 호출하고 나 인스턴스를 생성하면 시스템은 즉시 ‘this’ 변수와 연관된 콘텐츠로 창 객체의 존재를 등록합니다. 따라서 콜백 함수의 컨텍스트 내에서 사용될 때 ‘this’의 참조는 새로 구성된 엔티티가 아닌 창 객체에 해당합니다.

이 글도 확인해 보세요:  내부에서 REST API 호출을 수행하는 방법 VS 코드

이 문제를 해결하기 위한 한 가지 방법은 `bind()` 메서드를 사용하여 ‘person’ 함수를 새로 생성된 엔티티에 연결하는 것입니다:

 function person(name){
  this.name = name
  setTimeout(function() {
    console.log(this)
  }.bind(this), 1000)
}

const me = new person("Kingsley") // returns the me object

앞서 언급한 조정을 통해 콜백 함수 내에서 ‘this’의 값은 생성자 프로세스 중에 설정된 ‘me’ 객체에 해당하게 됩니다.

콜백 함수와 관련된 문제를 완화하기 위한 한 가지 대안은 기존 함수 선언에서 발생할 수 있는 잠재적 문제를 완화하는 데 도움이 되는 화살표 함수를 활용하는 것입니다.

“this” 화살표 함수 내부

화살표 함수 사용의 한 가지 장점은 특정 컨텍스트나 객체에 바인딩되는 콜백 함수를 생성하기 위해 `bind()` 메서드를 사용할 필요가 없다는 것입니다. 대신 화살표 함수는 주변 코드의 어휘 범위를 자동으로 상속하므로 추가 바인딩 프로세스 없이도 해당 범위 내의 변수에 액세스할 수 있습니다. 따라서 단일 표현식을 직접 실행해야 하는 특정 유형의 프로그래밍 작업에 더욱 간결하고 효율적인 옵션이 될 수 있습니다.

 function person(name){
  this.name = name
  setTimeout(() => {
    console.log(this)
  }, 1000)
}

const me = new person("Kingsley") // returns the me object

자바스크립트에 대해 더 알아보기

자바스크립트의 다양한 문맥에서 대명사 ‘this’의 활용에 대해 포괄적으로 이해하면 언어의 필수 구성 요소로서 그 중요성과 다용도성을 이해할 수 있습니다. 자바스크립트를 처음 접하는 분들에게 프로그래밍 언어의 기본 원리와 작동 메커니즘을 탐구하는 것은 숙련도와 숙달도를 키우는 데 도움이 될 것입니다.

By 최은지

윈도우(Windows)와 웹 서비스에 대한 전문 지식을 갖춘 노련한 UX 디자이너인 최은지님은 효율적이고 매력적인 디지털 경험을 개발하는 데 탁월한 능력을 발휘합니다. 사용자의 입장에서 생각하며 누구나 쉽게 접근하고 즐길 수 있는 콘텐츠를 개발하는 데 주력하고 있습니다. 사용자 경험을 향상시키기 위해 연구를 거듭하는 은지님은 All Things N 팀의 핵심 구성원으로 활약하고 있습니다.