๊ด€๋ฆฌ ๋ฉ”๋‰ด

Daehyunii's Dev-blog

22์žฅ this ๋ณธ๋ฌธ

22.1 this ํ‚ค์›Œ๋“œ

  ๊ฐ์ฒด์˜ ๋™์ž‘์„ ๋‚˜ํƒ€๋‚ด๋Š” ๋ฉ”์„œ๋“œ๋Š” ์ž์‹ ์ด ์†ํ•œ ๊ฐ์ฒด์˜ ์ƒํƒœ, ์ฆ‰ ํ”„๋กœํผํ‹ฐ๋ฅผ ์ฐธ์กฐํ•˜๊ณ  ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•œ๋‹ค. ์ด๋•Œ ๋ฉ”์„œ๋“œ๊ฐ€ ์ž์‹ ์ด ์†ํ•œ ๊ฐ์ฒด์˜ ํ”„๋กœํผํ‹ฐ๋ฅผ ์ฐธ์กฐํ•˜๋ ค๋ฉด ๋จผ์ € ์ž์‹ ์ด ์†ํ•œ ๊ฐ์ฒด๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ์‹๋ณ„์ž๋ฅผ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•œ๋‹ค. ๊ฐ์ฒด ๋ฆฌํ„ฐ๋Ÿด๋กœ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๊ฒฝ์šฐ์—๋Š” ๋ฉ”์„œ๋“œ ๋‚ด๋ถ€์—์„œ ๋ฉ”์„œ๋“œ ์ž์‹ ์ด ์†ํ•œ ๊ฐ์ฒด๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ์‹๋ณ„์ž๋ฅผ ์žฌ๊ท€์ ์œผ๋กœ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ๋‹ค.

const circle = {
    radius : 5,
    getDiameter(){
        return 2 * circle.radius // ์žฌ๊ท€์ ์œผ๋กœ ์ฐธ์กฐ
    }
};

console.log(circle.getDiameter()); // 10

  ํ•˜์ง€๋งŒ, ์ƒ์„ฑ์ž ํ•จ์ˆ˜์˜ ๊ฒฝ์šฐ ์ƒ์„ฑ์ž ํ•จ์ˆ˜ ๋‚ด๋ถ€์—์„œ๋Š” ํ”„๋กœํผํ‹ฐ ๋˜๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ์ถ”๊ฐ€ํ•˜๊ธฐ ์œ„ํ•ด ์ž์‹ ์ด ์ƒ์„ฑํ•  ์ธ์Šคํ„ด์Šค๋ฅผ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•˜๋Š”๋ฐ, ์ƒ์„ฑ์ž ํ•จ์ˆ˜์— ์˜ํ•œ ๊ฐ์ฒด ์ƒ์„ฑ ๋ฐฉ์‹์€ ๋จผ์ € ์ƒ์„ฑ์ž ํ•จ์ˆ˜๋ฅผ ์ •์˜ํ•œ ์ดํ›„ new ์—ฐ์‚ฐ์ž์™€ ํ•จ๊ป˜ ์ƒ์„ฑ์ž ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๋‹จ๊ณ„๊ฐ€ ์ถ”๊ฐ€๋กœ ํ•„์š”ํ•˜๋‹ค. ์ƒ์„ฑ์ž ํ•จ์ˆ˜๋ฅผ ์ •์˜ํ•˜๋Š” ์‹œ์ ์—๋Š” ์•„์ง ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•˜๊ธฐ ์ด์ „์ด๋ฏ€๋กœ ์ƒ์„ฑ์ž ํ•จ์ˆ˜๊ฐ€ ์ƒ์„ฑํ•  ์ธ์Šคํ„ด์Šค๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ์‹๋ณ„์ž๋ฅผ ์•Œ ์ˆ˜ ์—†๋‹ค. ์ด๋ฅผ ์œ„ํ•ด ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋Š” this๋ผ๋Š” ํŠน์ˆ˜ํ•œ ์‹๋ณ„์ž๋ฅผ ์ œ๊ณตํ•œ๋‹ค. this๋Š” ์ž์‹ ์ด ์†ํ•œ ๊ฐ์ฒด ๋˜๋Š” ์ž์‹ ์ด ์ƒ์„ฑํ•  ์ธ์Šคํ„ด์Šค๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ์ž๊ธฐ ์ฐธ์กฐ ๋ณ€์ˆ˜๋‹ค. this๋ฅผ ํ†ตํ•ด ์ž์‹ ์ด ์†ํ•œ ๊ฐ์ฒด ๋˜๋Š” ์ž์‹ ์ด ์ƒ์„ฑํ•  ์ธ์Šคํ„ด์Šค์˜ ํ”„๋กœํผํ‹ฐ๋‚˜ ๋ฉ”์„œ๋“œ๋ฅผ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ๋‹ค.

const circle = {
    radius : 5,
    getDiameter(){
        return 2 * this.radius // circle๊ฐ์ฒด๊ฐ€ ํ•ด๋‹น ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ–ˆ์œผ๋ฏ€๋กœ, circle์„ ๊ฐ€๋ฆฌํ‚ด
    }
};

console.log(circle.getDiameter()); // 10

  ๊ฐ์ฒด ๋ฆฌํ„ฐ๋Ÿด์˜ ๋ฉ”์„œ๋“œ ๋‚ด๋ถ€์—์„œ์˜ this๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•œ ๊ฐ์ฒด, ์ฆ‰ circle์„ ๊ฐ€๋ฆฌํ‚จ๋‹ค. ์ƒ์„ฑ์ž ํ•จ์ˆ˜๋กœ ํ˜ธ์ถœ๋˜๋Š” ๊ฒฝ์šฐ, ์ƒ์„ฑ์ž ํ•จ์ˆ˜ ๋‚ด๋ถ€์˜ this๋Š” ์ƒ์„ฑ์ž ํ•จ์ˆ˜๊ฐ€ ์ƒ์„ฑํ•  ์ธ์Šคํ„ด์Šค๋ฅผ ๊ฐ€๋ฆฌํ‚จ๋‹ค.

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

const circle1 = new Circle(10);
console.log(circle1.getDiameter()); // 20

  ์œ„์˜ ์ฝ”๋“œ์ฒ˜๋Ÿผ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์˜ this๋Š” ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋˜๋Š” ๋ฐฉ์‹์— ๋”ฐ๋ผ this์— ๋ฐ”์ธ๋”ฉ๋  ๊ฐ’์ด ๋™์ ์œผ๋กœ ๊ฒฐ์ •๋œ๋‹ค.

 

22.2 ํ•จ์ˆ˜ ํ˜ธ์ถœ ๋ฐฉ์‹๊ณผ this ๋ฐ”์ธ๋”ฉ

  this ๋ฐ”์ธ๋”ฉ์€ ํ•จ์ˆ˜ ํ˜ธ์ถœ ๋ฐฉ์‹, ์ฆ‰ ํ•จ์ˆ˜๊ฐ€ ์–ด๋–ป๊ฒŒ ํ˜ธ์ถœ๋˜์—ˆ๋Š”์ง€์— ๋”ฐ๋ผ ๋™์ ์œผ๋กœ ๊ฒฐ์ •๋œ๋‹ค. ํ•จ์ˆ˜๋Š” ๋‹ค์–‘ํ•œ ๋ฐฉ์‹์— ์˜ํ•ด ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๋‹ค. 

1. ์ผ๋ฐ˜ ํ•จ์ˆ˜ ํ˜ธ์ถœ

2. ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ

3. ์ƒ์„ฑ์ž ํ•จ์ˆ˜ ํ˜ธ์ถœ

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

 

22.2.1 ์ผ๋ฐ˜ ํ•จ์ˆ˜ ํ˜ธ์ถœ

  ๊ธฐ๋ณธ์ ์œผ๋กœ this์—๋Š” ์ „์—ญ ๊ฐ์ฒด๊ฐ€ ๋ฐ”์ธ๋”ฉ ๋œ๋‹ค. ์ค‘์ฒฉ ํ•จ์ˆ˜๋ฅผ ์ผ๋ฐ˜ ํ•จ์ˆ˜๋กœ ํ˜ธ์ถœํ•˜๋ฉด ํ•จ์ˆ˜ ๋‚ด๋ถ€์˜ this์— ์ „์—ญ ๊ฐ์ฒด๊ฐ€ ๋ฐ”์ธ๋”ฉ๋œ๋‹ค. ์ฝœ๋ฐฑ ํ•จ์ˆ˜๊ฐ€ ์ผ๋ฐ˜ ํ•จ์ˆ˜๋กœ ํ˜ธ์ถœ๋œ๋‹ค๋ฉด ์ฝœ๋ฐฑ ํ•จ์ˆ˜ ๋‚ด๋ถ€์˜ this์—๋„ ์ „์—ญ ๊ฐ์ฒด๊ฐ€ ๋ฐ”์ธ๋”ฉ๋œ๋‹ค. ์ฆ‰, ์–ด๋– ํ•œ ํ•จ์ˆ˜๋ผ๋„ ์ผ๋ฐ˜ ํ•จ์ˆ˜๋กœ ํ˜ธ์ถœ๋˜๋ฉด this์— ์ „์—ญ ๊ฐ์ฒด๊ฐ€ ๋ฐ”์ธ๋”ฉ๋œ๋‹ค.

function foo(){
    console.log(this); // window
    function bar(){
        console.log(this); // window
    }
    bar();
}
foo();

 

22.2.2 ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ

  ๋ฉ”์„œ๋“œ ๋‚ด๋ถ€์˜ this์—๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•œ ๊ฐ์ฒด, ์ฆ‰ ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•  ๋•Œ ๋ฉ”์„œ๋“œ ์ด๋ฆ„ ์•ž์˜ ๋งˆ์นจํ‘œ ์—ฐ์‚ฐ์ž ์•ž์— ๊ธฐ์ˆ ํ•œ ๊ฐ์ฒด๊ฐ€ ๋ฐ”์ธ๋”ฉ๋œ๋‹ค. ์ฃผ์˜ํ•ด์•ผํ•  ๊ฒƒ์€ ๋ฉ”์„œ๋“œ ๋‚ด๋ถ€์˜ this๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ์†Œ์œ ํ•œ ๊ฐ์ฒด๊ฐ€ ์•„๋‹Œ ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•œ ๊ฐ์ฒด์— ๋ฐ”์ธ๋”ฉ๋œ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค.

const person = {
    name : 'lee',
    getName(){
        return this.name;
    }
};

//๋ฉ”์„œ๋“œ๋กœ ํ˜ธ์ถœ
console.log(person.getName()); // lee(getName๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•œ ๊ฐ์ฒด์ธ person์— this๊ฐ€ ๋ฐ”์ธ๋”ฉ๋จ)


//์ผ๋ฐ˜ ํ•จ์ˆ˜๋กœ ํ˜ธ์ถœ
const getName = person.getName;
console.log(getName()); // ๋นˆ ๋ฌธ์ž์—ด ๋ฐ˜ํ™˜(window.name์—๋Š” ๋นˆ ๋ฌธ์ž์—ด์ด ๋“ค์–ด ์žˆ์Œ)
 

์œ„์˜ ์ฝ”๋“œ์ฒ˜๋Ÿผ getName ํ”„๋กœํผํ‹ฐ๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” ํ•จ์ˆ˜ ๊ฐ์ฒด, ์ฆ‰ getName ๋ฉ”์„œ๋“œ๋Š” ๋‹ค๋ฅธ ๊ฐ์ฒด์˜ ํ”„๋กœํผํ‹ฐ์— ํ• ๋‹นํ•˜๋Š” ๊ฒƒ์œผ๋กœ ๋‹ค๋ฅธ ๊ฐ์ฒด์˜ ๋ฉ”์„œ๋“œ๊ฐ€ ๋  ์ˆ˜๋„ ์žˆ๊ณ  ์ผ๋ฐ˜ ๋ณ€์ˆ˜์— ํ• ๋‹นํ•˜์—ฌ ์ผ๋ฐ˜ ํ•จ์ˆ˜๋กœ ํ˜ธ์ถœ๋  ์ˆ˜๋„ ์žˆ๋‹ค.(ํ˜ธ์ถœ ๋ฐฉ์‹์€ ๋‹ค์–‘ํ•˜๊ฒŒ ํ•  ์ˆ˜ ์žˆ์Œ) ๊ทธ๋Ÿฌ๋ฏ€๋กœ ๋ฉ”์„œ๋“œ ๋‚ด๋ถ€์˜ this๋Š” ํ”„๋กœํผํ‹ฐ๋กœ ๋ฉ”์„œ๋“œ๋ฅผ ๊ฐ€๋ฆฌํ‚ค๊ณ  ์žˆ๋Š” ๊ฐ์ฒด์™€๋Š” ๊ด€๊ณ„๊ฐ€ ์—†๊ณ  ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•œ ๊ฐ์ฒด์— ๋ฐ”์ธ๋”ฉ๋œ๋‹ค.

 

22.2.3 ์ƒ์„ฑ์ž ํ•จ์ˆ˜ ํ˜ธ์ถœ

  ์ƒ์„ฑ์ž ํ•จ์ˆ˜ ๋‚ด๋ถ€์˜ this์—๋Š” ์ƒ์„ฑ์ž ํ•จ์ˆ˜๊ฐ€ ๋ฏธ๋ž˜์— ์ƒ์„ฑํ•  ์ธ์Šคํ„ด์Šค๊ฐ€ ๋ฐ”์ธ๋”ฉ๋œ๋‹ค.

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

const circle1 = new Circle(10);
console.log(circle1.getDiameter()); // 20

๋งŒ์•ฝ new ์—ฐ์‚ฐ์ž ์—†์ด ์ƒ์„ฑ์ž ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๊ฒŒ ๋˜๋ฉด ์ผ๋ฐ˜ ํ•จ์ˆ˜๋กœ ํ˜ธ์ถœํ•˜๊ฒŒ ๋œ๋‹ค. ์ผ๋ฐ˜ ํ•จ์ˆ˜๋กœ ํ˜ธ์ถœ๋˜๋Š” ๊ฒฝ์šฐ์˜ this๋Š” ์ „์—ญ ๊ฐ์ฒด๋ฅผ ๊ฐ€๋ฆฌํ‚จ๋‹ค.

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

const circle1 = Circle(10);
console.log(circle1); // undefined ๋ฐ˜ํ™˜(๋ฐ˜ํ™˜ ๊ฐ’์ด ์—†์œผ๋ฏ€๋กœ undefined ๋ฐ˜ํ™˜
//์ „๋ถ€ window ๊ฐ์ฒด์˜ ํ”„๋กœํผํ‹ฐ/๋ฉ”์„œ๋“œ๊ฐ€ ๋˜๋ฒ„๋ฆผ
console.log(window.radius); // 10
console.log(window.getDiameter()); // 20

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

  Function.prototype.apply/call/bind ๋ฉ”์„œ๋“œ๋Š” Function.prototype์˜ ๋ฉ”์„œ๋“œ๋‹ค. ์ฆ‰, ์ด๋“ค ๋ฉ”์„œ๋“œ๋Š” ๋ชจ๋“  ํ•จ์ˆ˜๊ฐ€ ์ƒ์†๋ฐ›์•„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. apply/call ๋ฉ”์„œ๋“œ๋Š” this๋กœ ์‚ฌ์šฉํ•  ๊ฐ์ฒด์™€ ์ธ์ˆ˜ ๋ฆฌ์ŠคํŠธ๋ฅผ ์ธ์ˆ˜๋กœ ์ „๋‹ฌ๋ฐ›์•„ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค. ์ฆ‰, ์ฒซ๋ฒˆ์งธ ์ธ์ˆ˜๋กœ this์™€ ๋ฐ”์ธ๋”ฉ ํ•  ๊ฐ์ฒด๋ฅผ ๋„ฃ๊ณ  ๋‘ ๋ฒˆ์งธ ์ธ์ˆ˜๋ถ€ํ„ฐ ํ˜ธ์ถœ ํ•  ํ•จ์ˆ˜์˜ ์ธ์ˆ˜๋ฅผ ์ง‘์–ด๋„ฃ๋Š”๋‹ค.(์ธ์ˆ˜ ์ „๋‹ฌ ๋ฐฉ์‹์— ์ฐจ์ด๋งŒ ์กด์žฌํ•จ)

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

const thisArg = { x : 1 };

console.log(getThisBinding()); // window

console.log(getThisBinding.apply(thisArg, [1,2,3])); 
// Arguments(3) [1, 2, 3, callee: ƒ, Symbol(Symbol.iterator): ƒ]
// {x: 1}

console.log(getThisBinding.call(thisArg, 1, 2)); 
// Arguments(2) [1, 2, callee: ƒ, Symbol(Symbol.iterator): ƒ]    
// {x: 1}

์ด์ฒ˜๋Ÿผ Function ํ”„๋กœํ† ํƒ€์ž… ๋ฉ”์„œ๋“œ๋ฅผ ํ™œ์šฉํ•˜์—ฌ ๋ช…์‹œ์ ์œผ๋กœ this ๋ฐ”์ธ๋”ฉ์„ ์ง€์ •ํ•˜๊ณ  ์ธ์ˆ˜๋ฅผ ์ „๋‹ฌํ•˜์—ฌ ๊ฐ„์ ‘์ ์œผ๋กœ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๋‹ค. Function.prototype.bind ๋ฉ”์„œ๋“œ๋Š” apply์™€ call ๋ฉ”์„œ๋“œ์™€ ๋‹ฌ๋ฆฌ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜์ง€ ์•Š๊ณ  this๋กœ ์‚ฌ์šฉํ•  ๊ฐ์ฒด๋งŒ ์ „๋‹ฌํ•œ๋‹ค. 

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

const thisArg = { x : 1 };

console.log(getThisBinding.bind(thisArg)()); // {x: 1}(ํ˜ธ์ถœ์„ ๋ณ„๋„๋กœ ํ•ด์ค˜์•ผํ•จ)