๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
Front-end/JS

this ์™€ this binding

by ciocio 2022. 4. 2.

๐Ÿ“Œ this

 

์ž์‹ ์ด ์†ํ•œ ๊ฐ์ฒด ๋˜๋Š” ์ž์‹ ์ด ์ƒ์„ฑํ•  ์ธ์Šคํ„ด์Šค๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ์ž๊ธฐ ์ฐธ์กฐ ๋ณ€์ˆ˜ self-referencing-variable ์ด๋‹ค.
this ๋ฅผ ํ†ตํ•ด ์ž์‹ ์ด ์†ํ•œ ๊ฐ์ฒด ๋˜๋Š” ์ž์‹ ์ด ์ƒ์„ฑํ•  ์ธ์Šคํ„ด์Šค์˜ property ๋‚˜ method ๋ฅผ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ๋‹ค.
๋‹จ, this ๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” ๊ฐ’ (this ๋ฐ”์ธ๋”ฉ) ์€ ํ•จ์ˆ˜ ํ˜ธ์ถœ ๋ฐฉ์‹์— ์˜ํ•ด ๋™์ ์œผ๋กœ ๊ฒฐ์ •๋œ๋‹ค.
1. ์ผ๋ฐ˜ ํ•จ์ˆ˜ ํ˜ธ์ถœ
2. ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ
3. ์ƒ์„ฑ์ž ํ•จ์ˆ˜ ํ˜ธ์ถœ
4. Function.prototype.apply/call/bind ๋ฉ”์„œ๋“œ์— ์˜ํ•œ (๊ฐ„์ ‘) ํ˜ธ์ถœ

 


 

๐Ÿ“Ž ์ผ๋ฐ˜ ํ•จ์ˆ˜ ํ˜ธ์ถœ 

๊ธฐ๋ณธ์ ์œผ๋กœ this ์—๋Š” ์ „์—ญ ๊ฐ์ฒด(global object)๊ฐ€ ๋ฐ”์ธ๋”ฉ๋œ๋‹ค.
(์–ด๋– ํ•œ ํ•จ์ˆ˜[์ค‘์ฒฉ ํ•จ์ˆ˜, ์ฝœ๋ฐฑ ํ•จ์ˆ˜ ํฌํ•จ]๋ผ๋„ ์ผ๋ฐ˜ ํ•จ์ˆ˜๋กœ ํ˜ธ์ถœ๋˜๋ฉด this ์— ์ „์—ญ ๊ฐ์ฒด๊ฐ€ ๋ฐ”์ธ๋”ฉ๋œ๋‹ค.)
strict mode ๊ฐ€ ์ ์šฉ๋˜๋ฉด, this ์—๋Š” undefined ๊ฐ€ ๋ฐ”์ธ๋”ฉ๋œ๋‹ค.

 

console.log(this)                      // ์ „์—ญ ๊ฐ์ฒด window

function foo(){
  console.log("foo's this: ", this);   // window
  function bar(){ 
    console.log("bar's this: ", this); // window
  }
  bar();
}
foo();

 

 

> this ์˜ ๋ชฉ์  ์ž์ฒด๊ฐ€ ๊ฐ์ฒด์˜ ํ”„๋กœํผํ‹ฐ๋‚˜ ๋ฉ”์„œ๋“œ๋ฅผ ์œ„ํ•œ ์ž๊ธฐ ์ฐธ์กฐ ๋ณ€์ˆ˜์ด๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

   ์ผ๋ฐ˜์ ์œผ๋กœ๋Š” ๊ฐ์ฒด์˜ ๋ฉ”์„œ๋“œ ๋‚ด๋ถ€ ๋˜๋Š” ์ƒ์„ฑ์ž ํ•จ์ˆ˜ ๋‚ด๋ถ€์—์„œ๋งŒ ์˜๋ฏธ๊ฐ€ ์žˆ๊ธฐ์— strict mode ์—์„œ๋Š” ์ ์šฉ๋˜์ง€ ์•Š๋Š”๋‹ค !-!

 

 

๐Ÿ“ ์ค‘์ฒฉ ํ•จ์ˆ˜, ์ผ๋ฐ˜ ํ•จ์ˆ˜๋กœ ํ˜ธ์ถœํ•˜๊ธฐ

 

var value = 1; 
// var ํ‚ค์›Œ๋“œ๋กœ ์„ ์–ธํ•œ ์ „์—ญ ๋ณ€์ˆ˜ value๋Š” ์ „์—ญ ๊ฐ์ฒด์˜ ํ”„๋กœํผํ‹ฐ์ด๋‹ค.
// const ํ‚ค์›Œ๋“œ๋กœ ์„ ์–ธํ•œ ์ „์—ญ ๋ณ€์ˆ˜ value๋Š” ์ „์—ญ ๊ฐ์ฒด์˜ ํ”„๋กœํผํ‹ฐ๊ฐ€ ์•„๋‹ˆ๋‹ค.
// const value = 1;

const obj = {
  value: 100,
  foo(){
    console.log("foo's this: ", this);               // {value: 100, foo: โจ}
    console.log("foo's this.value: ". this.value);   // 100
    
    // ๋ฉ”์„œ๋“œ ๋‚ด์—์„œ ์ •์˜ํ•œ ์ค‘์ฒฉ ํ•จ์ˆ˜
    function bar(){
      console.log("bar's this: ", this);             // window
      console.log("bar's this.value: ", this.value); // 1
    }
    
    // ๋ฉ”์„œ๋“œ ๋‚ด์—์„œ ์ •์˜ํ•œ ์ค‘์ฒฉ ํ•จ์ˆ˜๋„ ์ผ๋ฐ˜ ํ•จ์ˆ˜๋กœ ํ˜ธ์ถœํ•˜๋ฉด ๋‚ด๋ถ€์˜ this ์—๋Š” ์ „์—ญ ๊ฐ์ฒด๊ฐ€ ๋ฐ”์ธ๋”ฉ๋œ๋‹ค.
    bar();
  }
};

obj.foo();

 

 

๐Ÿ“ ์ฝœ๋ฐฑ ํ•จ์ˆ˜, ์ผ๋ฐ˜ ํ•จ์ˆ˜๋กœ ํ˜ธ์ถœํ•˜๊ธฐ

 

var value = 1;

const obj = {
  value: 100,
  foo(){
    console.log("foo's this: ", this);                    // {value: 100, foo: โจ}
    
    // ์ฝœ๋ฐฑ ํ•จ์ˆ˜ ๋‚ด๋ถ€์˜ this ์—๋Š” ์ „์—ญ ๊ฐ์ฒด๊ฐ€ ๋ฐ”์ธ๋”ฉ๋œ๋‹ค.
    setTimeout(function(){
      console.log("callback's this: ", this);             // window
      console.log("callback's this.value: ", this.value); // 1
    }. 100);
  }
};

obj.foo();

 

> ๊ทธ๋ ‡์ง€๋งŒ ์™ธ๋ถ€ ํ•จ์ˆ˜์ธ ๋ฉ”์„œ๋“œ์™€ ์ค‘์ฒฉ ํ•จ์ˆ˜/์ฝœ๋ฐฑ ํ•จ์ˆ˜์˜ this ๊ฐ€ ์ผ์น˜ํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ๊ฒƒ์€ 

   ์ค‘์ฒฉ ํ•จ์ˆ˜/์ฝœ๋ฐฑ ํ•จ์ˆ˜๊ฐ€ ํ—ฌํผ ํ•จ์ˆ˜๋กœ ๋™์ž‘ํ•˜๊ธฐ ์–ด๋ ต๊ฒŒ ๋งŒ๋“ ๋‹ค.

> ๊ทธ๋ž˜์„œ ๋ฉ”์„œ๋“œ ๋‚ด๋ถ€์˜ ์ค‘์ฒฉ ํ•จ์ˆ˜/์ฝœ๋ฐฑ ํ•จ์ˆ˜์˜ this ๋ฐ”์ธ๋”ฉ๊ณผ ๋ฉ”์„œ๋“œ์˜ this ๋ฐ”์ธ๋”ฉ์„ ์ผ์น˜์‹œํ‚ค๋Š” ๋ฐฉ๋ฒ•์ด ์กด์žฌํ•œ๋‹ค.

 

 

•  1. ๋ณ€์ˆ˜ ํ• ๋‹น

 

var value = 1;

const obj = {
  value: 100,
  foo(){
    // this ๋ฐ”์ธ๋”ฉ(obj)์„ ๋ณ€์ˆ˜ that ์— ํ• ๋‹น
    const that = this;
    
    // ์ฝœ๋ฐฑ ํ•จ์ˆ˜ ๋‚ด๋ถ€์—์„œ this ๋Œ€์‹  that ์„ ์ฐธ์กฐ
    setTimeout(function(){
      console.log(that.value); // 100
    }, 100);
  }
};

obj.foo();

 

•  2. apply, call, bind ๋ฉ”์„œ๋“œ ์‚ฌ์šฉํ•ด ์ง์ ‘ ๋ฐ”์ธ๋”ฉ

 

var value = 1;

const obj = {
  value: 100,
  foo(){
    // ์ฝœ๋ฐฑ ํ•จ์ˆ˜์— ๋ช…์‹œ์ ์œผ๋กœ this๋ฅผ ๋ฐ”์ธ๋”ฉํ•œ๋‹ค.
    setTimeout(function(){
      console.log(this.value); // 100
    }.bind(this),100);
  }
};

obj.foo();

 

•  3. ํ™”์‚ดํ‘œ ํ•จ์ˆ˜ ์‚ฌ์šฉ

 

var value = 1;

const obj = {
  value: 100,
  foo(){
    // ํ™”์‚ดํ‘œ ํ•จ์ˆ˜ ๋‚ด๋ถ€์˜ this๋Š” ์ƒ์œ„ ์Šค์ฝ”ํ”„์˜ this๋ฅผ ๊ฐ€๋ฆฌํ‚จ๋‹ค โ—โ—
    setTimeout(() => console.log(this.value), 100); // 100
  }
};

obj.foo();

 

 

๐Ÿ“Ž ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ 

๋ฉ”์„œ๋“œ ๋‚ด๋ถ€์˜ this ์—๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•œ ๊ฐ์ฒด๊ฐ€ ๋ฐ”์ธ๋”ฉ๋œ๋‹ค.
โ€ป ๋ฉ”์„œ๋“œ ๋‚ด๋ถ€์˜ this ๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ์†Œ์œ ํ•œ ๊ฐ์ฒด๊ฐ€ ์•„๋‹Œโ— ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•œ ๊ฐ์ฒด์— ๋ฐ”์ธ๋”ฉ๋œ๋‹ค.

 

function Person(name){
  this.name = name;
}

Person.prototype.getName = function(){
  return this.name;
};

const me = new Person('Lee');

// getName ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•œ ๊ฐ์ฒด๋Š” me๋‹ค.
console.log(me.getName());                          // Lee

Person.prototype.name = 'Kim';

// getName ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•œ ๊ฐ์ฒด๋Š” Person.prototype์ด๋‹ค.
console.log(Person.prototype.getName());            // Kim


// ๋ธŒ๋ผ์šฐ์ € ํ™˜๊ฒฝ์—์„œ window.name ์€ ๋ธŒ๋ผ์šฐ์ € ์ฐฝ์˜ ์ด๋ฆ„์„ ๋‚˜ํƒ€๋‚ด๋Š” ๋นŒํŠธ์ธ ํ”„๋กœํผํ‹ฐ์ด๊ณ , ๊ธฐ๋ณธ๊ฐ’์€ ''์ด๋‹ค.
// Node.js ํ™˜๊ฒฝ์—์„œ window.name ์€ undefined ์ด๋‹ค.

 

 

๐Ÿ“Ž ์ƒ์„ฑ์ž ํ•จ์ˆ˜ ํ˜ธ์ถœ 

 

function Circle(){
  // ์ƒ์„ฑ์ž ํ•จ์ˆ˜ ๋‚ด๋ถ€์˜ this ๋Š” ์ƒ์„ฑ์ž ํ•จ์ˆ˜๊ฐ€ ์ƒ์„ฑํ•  ์ธ์Šคํ„ด์Šค๋ฅผ ๊ฐ€๋ฆฌํ‚จ๋‹ค.
  this.radius = radius;
  this.getDiameter = function(){
    return 2 * this.radius;
  };
}

// ๋ฐ˜์ง€๋ฆ„์ด 5์ธ Circle ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑ
const circle_5 = new Circle(5);
// ๋ฐ˜์ง€๋ฆ„์ด 10์ธ Circle ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑ
const circle_10 = new Circle(10);

console.log(circle_5.getDiameter());
console.log(circle_10.getDiameter());

 

 

๐Ÿ“Ž Function.prototype.apply/call/bind ๋ฉ”์„œ๋“œ์— ์˜ํ•œ (๊ฐ„์ ‘) ํ˜ธ์ถœ 

apply, call, bind ๋ฉ”์„œ๋“œ๋Š” Function.prototype ์˜ ๋ฉ”์„œ๋“œ์ด๋‹ค.
apply, call ๋ฉ”์„œ๋“œ๋Š” ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด์„œ ์ฒซ ๋ฒˆ์งธ ์ธ์ˆ˜๋กœ ์ „๋‹ฌํ•œ ํŠน์ • ๊ฐ์ฒด๋ฅผ ํ˜ธ์ถœํ•œ ํ•จ์ˆ˜์˜ this ์— ๋ฐ”์ธ๋”ฉํ•œ๋‹ค.
bind ๋ฉ”์„œ๋“œ๋Š” ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜์ง€ ์•Š๊ณ  this ๋กœ ์‚ฌ์šฉํ•  ๊ฐ์ฒด๋งŒ ์ „๋‹ฌํ•œ๋‹ค.
(๊ทธ๋ž˜์„œ bind ๋ฉ”์„œ๋“œ๋กœ apply, call ๋ฉ”์„œ๋“œ์™€ ๊ฐ™์€ ํšจ๊ณผ๋ฅผ ๋‚ด๋ ค๋ฉด ๋ช…์‹œ์ ์œผ๋กœ ํ˜ธ์ถœํ•ด์ค˜์•ผํ•œ๋‹ค.)

 

function getThisBinding(){
  console.log(arguments);
  return this;
}

const thisArg = {a: 1}; // this๋กœ ์‚ฌ์šฉํ•  ๊ฐ์ฒด

// apply ๋ฉ”์„œ๋“œ๋Š” ํ˜ธ์ถœํ•  ํ•จ์ˆ˜์˜ ์ธ์ˆ˜๋ฅผ ๋ฐฐ์—ด๋กœ ๋ฌถ์–ด ์ „๋‹ฌํ•œ๋‹ค.(๋ฐฐ์—ด ๋˜๋Š” ์œ ์‚ฌ ๋ฐฐ์—ด ๊ฐ์ฒด)
console.log(getThisBinding.apply(thisArg, [1, 2, 3]));
// Arguments(3) [1, 2, 3, callee: โจ, Symbol(Symbol.iterator): โจ]
// {a: 1}

// call ๋ฉ”์„œ๋“œ๋Š” ํ˜ธ์ถœํ•  ํ•จ์ˆ˜์˜ ์ธ์ˆ˜๋ฅผ ์‰ผํ‘œ๋กœ ๊ตฌ๋ถ„ํ•œ ๋ฆฌ์ŠคํŠธ ํ˜•์‹์œผ๋กœ ์ „๋‹ฌํ•œ๋‹ค. 
console.log(getThisBinding.call(thisArg, 1, 2, 3));
// Arguments(3) [1, 2, 3, callee: โจ, Symbol(Symbol.iterator): โจ]
// {a: 1}

 

function getThisBinding(){
  return this;
}

// this ๋กœ ์‚ฌ์šฉํ•  ๊ฐ์ฒด
const thisArg = {a: 1};

// bind ๋ฉ”์„œ๋“œ๋Š” ํ•จ์ˆ˜์— this๋กœ ์‚ฌ์šฉํ•  ๊ฐ์ฒด๋ฅผ ์ „๋‹ฌํ•œ๋‹ค.
// bind ๋ฉ”์„œ๋“œ๋Š” ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜์ง€๋Š” ์•Š๋Š”๋‹ค. ๊ทธ๋ž˜์„œ ๋ช…์‹œ์ ์œผ๋กœ ํ˜ธ์ถœํ•ด์ค˜์•ผํ•œ๋‹ค !
console.log(getThisBinding.bind(thisArg));   // getThisBinding
console.log(getThisBinding.bind(thisArg)()); // {a: 1}

 

 

๐Ÿ“Lexical Scope ์™€ this ๋ฐ”์ธ๋”ฉ

 

Lexical Scope ๋Š” ํ•จ์ˆ˜ ์ •์˜๊ฐ€ ํ‰๊ฐ€๋˜์–ด ํ•จ์ˆ˜ ๊ฐ์ฒด๊ฐ€ ์ƒ์„ฑ๋˜๋Š” ์‹œ์ ์— ์ƒ์œ„ ์Šค์ฝ”ํ”„๋ฅผ ๊ฒฐ์ •ํ•œ๋‹ค.
this ๋ฐ”์ธ๋”ฉ์€ ํ•จ์ˆ˜ ํ˜ธ์ถœ ์‹œ์ ์— ๊ฒฐ์ •๋œ๋‹ค.

 

 

๐Ÿ“ ์ •๋ฆฌ

 

ํ•จ์ˆ˜ ํ˜ธ์ถœ ๋ฐฉ์‹ this ๋ฐ”์ธ๋”ฉ
์ผ๋ฐ˜ ํ•จ์ˆ˜ ํ˜ธ์ถœ ์ „์—ญ ๊ฐ์ฒด
๋ฉ”์„œ๋“œ ํ˜ธ์ถœ ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•œ ๊ฐ์ฒด
์ƒ์„ฑ์ž ํ•จ์ˆ˜ ํ˜ธ์ถœ ์ƒ์„ฑ์ž ํ•จ์ˆ˜๊ฐ€ ๋ฏธ๋ž˜์— ์ƒ์„ฑํ•  ์ธ์Šคํ„ด์Šค
Function.prototype.apply/call/bind ๋ฉ”์„œ๋“œ์— ์˜ํ•œ ๊ฐ„์ ‘ ํ˜ธ์ถœ Function.prototype.apply/call/bind ๋ฉ”์„œ๋“œ์—
์ฒซ ๋ฒˆ์งธ ์ธ์ˆ˜๋กœ ์ „๋‹ฌํ•œ ๊ฐ์ฒด

 

 

• ์ฐธ๊ณ  ์ž๋ฃŒ

๋ชจ๋˜ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ DEEP DIVE - ์ด์›…๋ชจ

๋ฐ˜์‘ํ˜•

๋Œ“๊ธ€