JavaScript

JavaScript

kimddakki 2022. 5. 13. 12:31
this : 이것

this란 자신이 속한 객체 또는 자신이 생성할 인스턴스를 가리키는 자기 참조 변수 (self-refernece-variable)이다.

대부분의 경우 this의 값은 함수를 호출한 방법에 의해 결정된다.

 - ES5는 함수를 어떻게 호출 했는지 상관하지 않고 this 값을 설정할 수 있는 bind 메서드를 도입

 - ES2015는 스스로의 this 바인딩을 제공하지 않는 화살표 함수 추가(이는 렉시컬 컨텍스트안의 this값을 유지합니다)


전역 문맥

전역 실행 맥락에서는 this는 엄격 여부에 관계 없이 전역 객체를 참조합니다.

a = 37;
console.log(globalThis);
console.log(globalThis.a); // 37
console.log(a); // 37
console.log(global);
console.log(global.a); // 37
console.log(a); // 37
console.log(global === globalThis); // true
함수 문맥

함수 내부에서 this의 값은 함수를 호출한 방법에 의해 좌우됩니다.

 

 - 단순 호출

기본값으로는 globalThis인 전역 객체를 참조합니다

function f1() {
  return this;
}

console.log(f1() === global); // true
console.log(f1() === globalThis); // true

1. this의 값을 한 문맥에서 다른 문맥으로 넘거가기 위해선 call()이나 apply() 메서드를 사용하면 된다.

function update(bitrhYear, job) {
  this.bitrhYear = bitrhYear;
  this.job = job;
}
update.call(kim, 1995, "Student");
console.log(kim); //{ name: 'kim', bitrhYear: 1995, job: 'Student' }

// apply : apply는 매개변수를 처리하는 방법을 제외하면 call과 완전히 같다
// call은 일반적인 함수와 마찬가지로 매개변수를 직접 받지만 apply는 매개변수를 배열로 받는다.

update.apply(lee, [1995, "Student"]);
console.log(lee); //{ name: 'lee', bitrhYear: 1995, job: 'Student' }

2. bind() 메서드는 call, apply와 다른 점은 함수를 실행하지 않는다는 점이다. 대신 bound함수를 리턴한다. 

// 새 함수의 this는 호출 방식과 상관없이 bind의 첫 번째 매개 변수로 고정이 된다.

const updateKim = update.bind(kim);
updateKim(1995, "Student");
console.log(kim);

const user = {
  name: "Kim",
  showName: function () {
    console.log(`hello ${this.name}`);
  },
};

user.showName(); // hello kim
let fn = user.showName;
fn(); // hello undefined
fn.call(user); // hello kim
fn.bind(user); // hello kim

const bindFn = fn.bind(user);
bindFn(); // hello kim

화살표 함수의 this

화살표 함수에서 this는 자신을 감싼 정적 범위입니다. 전역 코드에서는 전역 객체를 가리킵니다.

 

어떤 방법을 사용하든 foo의 this는 생성 시점의 것으로 설정됩니다(위 예시에서는 global 객체). 다른 함수 내에서 생성된 화살표 함수에도 동일하게 적용됩니다. this는 싸여진 렉시컬 컨텍스트의 것으로 유지됩니다.

// this를 반환하는 메소드 bar를 갖는 obj를 생성합니다.
// 반환된 함수는 화살표 함수로 생성되었으므로,
// this는 감싸진 함수의 this로 영구적으로 묶입니다.
// bar의 값은 호출에서 설정될 수 있으며, 이는 반환된 함수의 값을 설정하는 것입니다.
var obj = {
  bar: function () {
    var x = () => this;
    return x;
  },
};

// obj의 메소드로써 bar를 호출하고, this를 obj로 설정
// 반환된 함수로의 참조를 fn에 할당
var fn = obj.bar();
console.log(fn); //function : x

// this 설정 없이 fn을 호출하면,
// 기본값으로 global 객체 또는 엄격 모드에서는 undefined
console.log(fn() === obj); // true

// 호출 없이 obj의 메소드를 참조한다면 주의하세요.
var fn2 = obj.bar;
// 화살표 함수의 this를 bar 메소드 내부에서 호출하면
// fn2의 this를 따르므로 window를 반환할것입니다.
console.log(fn2()() == globalThis); // true

화살표 함수의 this는 무조건! 실행했을 때 (익명함수니까) 자신을 감싼 정적 범위다!! 


객체의 매서드로서 this

함수를 어떤 객체의 메서드로 호출하면 this의 값은 그 객체를 사용합니다.

const a = {
  b: "b",
  f: function () {
    console.log(this.b);
  },
};

a.f(); // b

이러한 행동이 함수가 정의된 방법이나 위치에 전혀 영향을 받지 않는 것에 유의 해야 한다.

간단하게 함수를 먼저 정의하고 나중에 객체의 매서드로 추가해도 똑같이 this가 반영된다!

const o = { porp: 37 };

function b() {
  return this.porp;
}
o.f = b;
console.log(o.f()); // 37

이는 함수가 o의 멤버 f로부터 호출 된 것만이 중요하다는 것을 말한다!!

 

마찬가지로, 이 this 바인딩은 가장 즉각으로 멤버 대상에 영향을 받는다. 다음 예제에서, 함수를 실행할 때, 객체 o.b의 메소드 g 로서 호출한다. 이것이 실행되는 동안, 함수 내부의 this는 o.b를 나타낸다. 객체는 그 자신이 o의 멤버 중 하나라는 사실은 중요하지 않다. 가장 즉각적인 참조가 중요한 것이다.

 

const o = { prop: 37 };

function b() {
  return this.prop;
}
o.f = b;
console.log(o.f()); // 37

o.b = { g: b, prop: 42 };
console.log(o.b.g()); // logs 42

 

 

this - JavaScript | MDN

JavaScript에서 함수의 this 키워드는 다른 언어와 조금 다르게 동작합니다. 또한 엄격 모드와 비엄격 모드에서도 일부 차이가 있습니다.

developer.mozilla.org