๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
JavaScript

[JavaScript] ์‹คํ–‰ ์ปจํ…์ŠคํŠธ์™€ this๋ฐ”์ธ๋”ฉ(this binding)

by junvely 2023. 4. 5.

 

๐Ÿ’ก๋ฆฌ๋งˆ์ธ๋“œ

- ์‹คํ–‰ ์ปจํ…์ŠคํŠธ๋Š” ์‹คํ–‰ํ•  ์ฝ”๋“œ์— ์ œ๊ณตํ•  ํ™˜๊ฒฝ ์ •๋ณด๋“ค์„ ๋ชจ์•„๋†“์€ ๊ฐ์ฒด์ด๋‹ค.
- ๊ทธ ๊ฐ์ฒด ์•ˆ์—๋Š” 3๊ฐ€์ง€๊ฐ€ ์กด์žฌํ•œ๋‹ค.
   โœ“ VariableEnvironment
   โœ“ LexicalEnvironment
   โœ“ ThisBindings

์ƒํ™ฉ์— ๋”ฐ๋ผ ๋‹ฌ๋ผ์ง€๋Š” this

this๋Š” ์‹คํ–‰ ์ปจํ…์ŠคํŠธ๊ฐ€ ์ƒ์„ฑ๋  ๋•Œ ๊ฒฐ์ •๋œ๋‹ค. ์ด ๋ง์„ this๋ฅผ bindํ•œ๋‹ค(=๋ฌถ๋Š”๋‹ค) ๋ผ๊ณ ๋„ ํ•œ๋‹ค. ๋‹ค์‹œ ๋งํ•˜๋ฉด this๋Š” ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•  ๋•Œ ๊ฒฐ์ •๋œ๋‹ค.

1. ์ „์—ญ ์—์„œ์˜ this

๋Ÿฐํƒ€์ž„ ํ™˜๊ฒฝ์— ๋”ฐ๋ผ this๋Š” window(๋ธŒ๋ผ์šฐ์ € ํ™˜๊ฒฝ) ๋˜๋Š” global(node ํ™˜๊ฒฝ)๋ฅผ ๊ฐ€๋ฆฌํ‚จ๋‹ค.

๋Ÿฐํƒ€์ž„ ํ™˜๊ฒฝ?

์—ฌ๋Ÿฌ๋ถ„๋“ค์ด javascript๋กœ ๋งŒ๋“ค์–ด๋†“์€ ํ”„๋กœ๊ทธ๋žจ์ด ๊ตฌ๋™์ค‘์ธ ํ™˜๊ฒฝ์„ ๋งํ•˜์ฃ . 
์šฐ๋ฆฌ๋Š” node ํŒŒ์ผ์ด๋ฆ„.js๋กœ vscode ์ƒ์—์„œ ๊ตฌ๋™ํ•˜๊ณ  ์žˆ์œผ๋‹ˆ node ํ™˜๊ฒฝ์ด๋ผ๊ณ  ํ•  ์ˆ˜ ์žˆ๊ตฌ์š”. 
html ํŒŒ์ผ ์•ˆ์— ์ˆจ๊ฒจ๋†“์•„์„œ ํฌ๋กฌ๋ธŒ๋ผ์šฐ์ € ๋“ฑ์—์„œ ์—ฐ๋‹ค๊ณ  ํ•œ๋‹ค๋ฉด ๋ธŒ๋ผ์šฐ์ € ํ™˜๊ฒฝ์ด๋ผ๊ณ  ํ•  ์ˆ˜ ์žˆ๊ฒ ๋„ค์š”.

=> ์ „์—ญ์—์„œ์˜ this๋Š” ๋ธŒ๋ผ์šฐ์ €์—์„œ๋Š” window, Nodeํ™˜๊ฒฝ์—์„œ๋Š” global์„ ๊ฐ€๋ฆฌํ‚จ๋‹ค.

// CASE1 : ํ•จ์ˆ˜
// ํ˜ธ์ถœ ์ฃผ์ฒด๋ฅผ ๋ช…์‹œํ•  ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์— this๋Š” ์ „์—ญ ๊ฐ์ฒด๋ฅผ ์˜๋ฏธํ•ด์š”.
var func = function (x) {
	console.log(this, x);
};
func(1); // Window { ... } 1

// CASE2 : ๋ฉ”์„œ๋“œ
// ํ˜ธ์ถœ ์ฃผ์ฒด๋ฅผ ๋ช…์‹œํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— this๋Š” ํ•ด๋‹น ๊ฐ์ฒด(obj)๋ฅผ ์˜๋ฏธํ•ด์š”.
// obj๋Š” ๊ณง { method: f }๋ฅผ ์˜๋ฏธํ•˜์ฃ ?
var obj = {
	method: func,
};
obj.method(2); // { method: f } 2

 

2. ๋ฉ”์†Œ๋“œ๋กœ์„œ ํ˜ธ์ถœํ•  ๋•Œ์™€, ํ•จ์ˆ˜์—์„œ ํ˜ธ์ถœํ•  ๋•Œ์˜ ์ฐจ์ด => ํ˜ธ์ถœํ•˜๋Š” ์‹คํ–‰ ์ฃผ์ฒด์— ๋”ฐ๋ผ this๊ฐ€ ๋‹ฌ๋ผ์ง„๋‹ค.

1) ํ•จ์ˆ˜์—์„œ์˜ this => ์ „์—ญ ๊ฐ์ฒด(window or global)

2) ๋ฉ”์†Œ๋“œ์—์„œ์˜ this => ํ˜ธ์ถœ์˜ ์ฃผ์ฒด

=> ๋”ฐ๋ผ์„œ ํ•จ์ˆ˜๋ฅผ ๋…๋ฆฝ์ ์œผ๋กœ ํ˜ธ์ถœ ์‹œ์—๋Š” this๊ฐ€ ํ•ญ์ƒ ์ „์—ญ๊ฐ์ฒด๋ฅผ ๊ฐ€๋ฆฌํ‚จ๋‹ค.

=> ๋ฉ”์†Œ๋“œ ๋‚ด๋ถ€ ํ•จ์ˆ˜์—์„œ๋„ ์˜ˆ์™ธ์—†๋‹ค. ๋ฉ”์„œ๋“œ ๋‚ด๋ถ€์˜ ํ•จ์ˆ˜ ์•ˆ์—์„œ this๋ฅผ ํ˜ธ์ถœํ•  ๊ฒฝ์šฐ, ๊ธฐ์กด ๋ฉ”์†Œ๋“œ ํ˜ธ์ถœ ์ฃผ์ฒด์— ๋Œ€ํ•œ this์˜ ์ •๋ณด๋ฅผ ์žƒ๊ณ  ์ „์—ญ๊ฐ์ฒด๋ฅผ ์ฐธ์กฐํ•œ๋‹ค. => ํ•จ์ˆ˜์ด๊ธฐ ๋•Œ๋ฌธ

var obj1 = {
	outer: function() {
		console.log(this); // (1) obj1
		var innerFunc = function() {
			console.log(this); // (2) winodw 
		innerFunc();

		var obj2 = {
			innerMethod: innerFunc // (3) obj2
		};
		obj2.innerMethod();
	}
};
obj1.outer();
๐Ÿ’ก์šฉ์–ด ๊ธฐ์–ต
AS - IS => ๊ธฐ์กด ๊ฒƒ ์˜๋ฏธ
TO - BE => ์ดํ›„ ๊ฒƒ ์˜๋ฏธ

 

3. ํ™”์‚ดํ‘œ ํ•จ์ˆ˜์—์„œ์˜ this

ES6์—์„œ ์ฒ˜์Œ ๋„์ž…๋œ ํ™”์‚ดํ‘œ ํ•จ์ˆ˜๋Š”, ์‹คํ–‰ ์ปจํ…์ŠคํŠธ๋ฅผ ์ƒ์„ฑํ•  ๋•Œ this ๋ฐ”์ธ๋”ฉ ๊ณผ์ • ์ž์ฒด๊ฐ€ ์—†๋‹ค(๋”ฐ๋ผ์„œ, this๋Š” ์ด์ „์˜ ๊ฐ’์ด ์œ ์ง€๋œ๋‹ค. => ๋ฉ”์†Œ๋“œ ๋‚ด๋ถ€์˜ ํ™”์‚ดํ‘œ ํ•จ์ˆ˜ ์•ˆ์—์„œ this๋ฅผ ํ˜ธ์ถœ ํ•  ๋•Œ, this ๋ฐ”์ธ๋”ฉ ์ž์ฒด๋ฅผ ํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์—, this์˜ ์ฐธ์กฐ ๊ด€๊ณ„๋ฅผ ์žƒ์ง€ ์•Š๊ณ  ๊ธฐ์กด์˜ ๋ฉ”์†Œ๋“œ์—์„œ ์ฐธ์กฐํ•œ ํ˜ธ์ถœ ๊ฐ์ฒด๋ฅผ ์—ฌ์ „ํžˆ ์ฐธ์กฐํ•œ๋‹ค.

var obj = {
	outer: function() {
		console.log(this); // (1) obj
		var innerFunc = () => {
			console.log(this); // (2) obj
		};
		innerFunc();
	}
}

obj.outer();

=> ES6์—์„œ๋Š” ํ•จ์ˆ˜ ๋‚ด๋ถ€์—์„œ this๊ฐ€ ์ „์—ญ๊ฐ์ฒด๋ฅผ ๋ฐ”๋ผ๋ณด๋Š” ๋ฌธ์ œ ๋•Œ๋ฌธ์— ํ™”์‚ดํ‘œํ•จ์ˆ˜๋ฅผ ๋„์ž…ํ–ˆ๋‹ค.

๐Ÿ’ก๋ฉด์ ‘์—์„œ ์ผ๋ฐ˜ ํ•จ์ˆ˜์™€ ํ™”์‚ดํ‘œ ํ•จ์ˆ˜์˜ ๊ฐ€์žฅ ํฐ ์ฐจ์ด์ ์€ ๋ฌด์—‡์ธ๊ฐ€์š”? 
๋ผ๊ณ  ๋ฌผ์œผ๋ฉด > this binding ์—ฌ๋ถ€๊ฐ€ ๊ฐ€์žฅ ์ ์ ˆํ•œ ๋‹ต

 

4. ์ฝœ๋ฐฑ ํ•จ์ˆ˜ ํ˜ธ์ถœ ์‹œ ๊ทธ ํ•จ์ˆ˜ ๋‚ด๋ถ€์—์„œ์˜ this

=> ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋„ ํ•จ์ˆ˜์ด๊ธฐ ๋•Œ๋ฌธ์— ๊ทธ ํ•จ์ˆ˜ ๋‚ด๋ถ€์—์„œ this ํ˜ธ์ถœ ์‹œ this๋ฅผ ์žƒ๊ณ  ์ „์—ญ ๊ฐ์ฒด๋ฅผ ์ฐธ์กฐํ•œ๋‹ค. (๋‹จ, ์ฝœ๋ฐฑ์—์„œ ํ™”์‚ดํ‘œ ํ•จ์ˆ˜ ์ง€์ •์‹œ this ๋ฐ”์ธ๋”ฉx ์ „์—ญ๊ฐ์ฒด ์ฐธ์กฐx)

ํ•˜์ง€๋งŒ ๋ณ„๋„ ์˜ˆ์™ธ๋กœ this๋ฅผ ์ง€์ •ํ•œ ๊ฒฝ์šฐ ๊ทธ ๋Œ€์ƒ์„ ์ฐธ์กฐํ•œ๋‹ค. ex) addEventListener

// ๋ณ„๋„ ์ง€์ • ์—†์Œ : ์ „์—ญ๊ฐ์ฒด
setTimeout(function () { console.log(this) }, 300);

// ๋ณ„๋„ ์ง€์ • ์—†์Œ : ์ „์—ญ๊ฐ์ฒด
[1, 2, 3, 4, 5].forEach(function(x) {
	console.log(this, x);
});

// addListener ์•ˆ์—์„œ์˜ this๋Š” ํ•ญ์ƒ ํ˜ธ์ถœํ•œ ์ฃผ์ฒด์˜ element๋ฅผ returnํ•˜๋„๋ก ์„ค๊ณ„๋˜์—ˆ์Œ
// ๋”ฐ๋ผ์„œ this๋Š” button์„ ์˜๋ฏธํ•จ
document.body.innerHTML += '<button id="a">ํด๋ฆญ</button>';
document.body.querySelector('#a').addEventListener('click', function(e) {
	console.log(this, e);
});

addEventListner ๋ฉ”์„œ๋“œ๋Š” ์ฝœ๋ฐฑ ํ•จ์ˆ˜ ํ˜ธ์ถœ ์‹œ, ์ž์‹ ์˜ this๋ฅผ ์ƒ์†ํ•˜๋ฏ€๋กœ, this๋Š” addEventListner์˜ ์•ž๋ถ€๋ถ„(button ํƒœ๊ทธ)์ด๋‹ค.

 

5. ์ƒ์„ฑ์ž ํ•จ์ˆ˜ ๋‚ด๋ถ€์—์„œ์˜ this

์ƒ์„ฑ์ž : ๊ตฌ์ฒด์ ์ธ ์ธ์Šคํ„ด์Šค => class์˜ constructor๋‚˜ ์ƒ์„ฑ์ž ํ•จ์ˆ˜์—์„œ์˜ ์ƒ์„ฑ์ž ํ•จ์ˆ˜ this.~๊ฐ€ ๋“ค์–ด์žˆ๋Š”..

=> ์ƒ์„ฑ์ž ํ•จ์ˆ˜์—์„œ์˜ tihs๋Š” ํ•ญ์ƒ ์ธ์Šคํ„ด์Šค๋ฅผ ์ง€์ •ํ•œ๋‹ค.

var Cat = function (name, age) { //์ƒ์„ฑ์ž
	this.bark = '์•ผ์˜น';
	this.name = name;
	this.age = age;
};

var choco = new Cat('์ดˆ์ฝ”', 7); //this : choco => ์ธ์Šคํ„ด์Šค
var nabi = new Cat('๋‚˜๋น„', 5);  //this : nabi

 

 

6. ๋ช…์‹œ์  this ๋ฐ”์ธ๋”ฉ

์ž๋™์œผ๋กœ ๋ถ€์—ฌ๋˜๋Š” ์ƒํ™ฉ๋ณ„ this์˜ ๊ทœ์น™์„ ๊นจ๊ณ  this์— ๋ณ„๋„์˜ ๊ฐ’์„ ์ €์žฅํ•˜๋Š” ๋ฐฉ๋ฒ•

1. call / apply / bind

var func = function (a, b, c) {
	console.log(this, a, b, c);
};

// no binding
func(1, 2, 3); // Window{ ... } 1 2 3

// ๋ช…์‹œ์  binding
// func ์•ˆ์— this์—๋Š” {x: 1}์ด binding๋ผ์š”
func.call({ x: 1 }, 4, 5, 6}; // { x: 1 } 4 5 6

2. ์œ ์‚ฌ๋ฐฐ์—ด๊ฐ์ฒด => Array.from()

// ์œ ์‚ฌ๋ฐฐ์—ด
var obj = {
	0: 'a',
	1: 'b',
	2: 'c',
	length: 3
};

// ๊ฐ์ฒด -> ๋ฐฐ์—ด
var arr = Array.from(obj);

// ์ฐ์–ด๋ณด๋ฉด ๋ฐฐ์—ด์ด ์ถœ๋ ฅ๋ฉ๋‹ˆ๋‹ค.
console.log(arr);

3. bind( ) => ์ฆ‰์‹œ ํ˜ธ์ถœํ•˜์ง€๋Š” ์•Š๊ณ  ๋ฏธ๋ฆฌ ๋„˜๊ฒจ๋ฐ›์€ this ๋ฐ ์ธ์ˆ˜๋“ค์„ ์ ์šฉ

var func = function (a, b, c, d) {
	console.log(this, a, b, c, d);
};
func(1, 2, 3, 4); // window๊ฐ์ฒด

// ํ•จ์ˆ˜์— this ๋ฏธ๋ฆฌ ์ ์šฉ
var bindFunc1 = func.bind({ x: 1 }); // ๋ฐ”๋กœ ํ˜ธ์ถœ๋˜์ง€๋Š” ์•Š์•„์š”! ๊ทธ ์™ธ์—๋Š” ๊ฐ™์•„์š”.
bindFunc1(5, 6, 7, 8); // { x: 1 } 5 6 7 8

// ๋ถ€๋ถ„ ์ ์šฉ ํ•จ์ˆ˜ ๊ตฌํ˜„
var bindFunc2 = func.bind({ x: 1 }, 4, 5); // 4์™€ 5๋ฅผ ๋ฏธ๋ฆฌ ์ ์šฉ
bindFunc2(6, 7); // { x: 1 } 4 5 6 7
bindFunc2(8, 9); // { x: 1 } 4 5 8 9
var obj = {
	outer: function() {
		console.log(this);
		var innerFunc = function () {
			console.log(this);
		}.bind(this); // innerFunc์— this๋ฅผ ๊ฒฐํ•ฉํ•œ ์ƒˆ๋กœ์šด ํ•จ์ˆ˜๋ฅผ ํ• ๋‹น
		innerFunc();
	}
};
obj.outer();

 

4. ํ™”์‚ดํ‘œ ํ•จ์ˆ˜๋Š” ์‹คํ–‰ ์ปจํ…์ŠคํŠธ ์ƒ์„ฑ ์‹œ, this๋ฅผ ๋ฐ”์ธ๋”ฉ ํ•˜์ง€ ์•Š์Œ

var obj = {
	outer: function () {
		console.log(this);
		var innerFunc = () => {
			console.log(this);
		};
		innerFunc();
	};
};
obj.outer();

 

 

 

* ์œ„ ๋‚ด์šฉ์€ ์ŠคํŒŒ๋ฅดํƒ€ ์ฝ”๋”ฉํด๋Ÿฝ JavaScript ๋ฌธ๋ฒ• ์ข…ํ•ฉ๋ฐ˜ ๊ฐ•์˜ ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค.