๐Ÿคฟ (10) ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ - this

Kayยท2023๋…„ 5์›” 11์ผ
0

Javascript

๋ชฉ๋ก ๋ณด๊ธฐ
11/12

"๋ฉ”์„œ๋“œ ํ˜ธ์ถœ ๋ฐฉ์‹์„ ์ด์šฉํ•  ๋•Œ์—๋Š” ํ™”์‚ดํ‘œ ํ•จ์ˆ˜๋ฅผ ์™œ ์“ฐ์ง€ ์•Š์•„์•ผํ• ๊นŒ?"

๋™์  ์Šค์ฝ”ํ”„์™€ ์ •์  ์Šค์ฝ”ํ”„

๋™์  ์Šค์ฝ”ํ”„(Dynamic scope)

ํ•จ์ˆ˜๋ฅผ ์–ด๋””์„œ "ํ˜ธ์ถœ"ํ•˜์˜€๋Š”์ง€์— ๋”ฐ๋ผ ์ƒ์œ„ ์Šค์ฝ”ํ”„๋ฅผ ๊ฒฐ์ •ํ•˜๋Š” ๊ฒƒ

์ •์  ์Šค์ฝ”ํ”„(Static Scope), ๋ ‰์‹œ์ปฌ ์Šค์ฝ”ํ”„(Lexical Scope)

ํ•จ์ˆ˜๋ฅผ ์–ด๋””์„œ "์„ ์–ธ"ํ•˜์˜€๋Š”์ง€์— ๋”ฐ๋ผ ์ƒ์œ„ ์Šค์ฝ”ํ”„๋ฅผ ๊ฒฐ์ •ํ•˜๋Š” ๊ฒƒ

๋‹ค์Œ ๊ธ€์—์„œ ์ €์ž๋Š” ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์˜ "ํ”„๋กœํ† ํƒ€์ž… ๊ธฐ๋ฐ˜์˜ ๊ฐ์ฒด์ง€ํ–ฅ", "๋ ‰์‹œ์ปฌ์Šค์ฝ”ํ”„", "this", "์Šค์ฝ”ํ”„"์™€ ๊ฐ™์€ ๊ฐœ๋…์— ๋Œ€ํ•ด ํ•œ ๋…ผ๋ฌธ์„ ์ฐธ๊ณ ํ•˜์—ฌ ์ด์•ผ๊ธฐ๋ฅผ ํ’€์–ด ์„ค๋ช…ํ•ด์ฃผ์‹ญ๋‹ˆ๋‹ค!
medium - ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋Š” ์™œ ํ”„๋กœํ† ํƒ€์ž…์„ ์„ ํƒํ–ˆ์„๊นŒ

์˜ˆ์‹œ

์ถœ์ฒ˜: tistory - [Javascript] ๋™์  ์Šค์ฝ”ํ”„? ์ •์  ์Šค์ฝ”ํ”„?

์˜ˆ์‹œ๋Š” c์–ธ์–ด์ด๋‹ค.

var x = 1;

function foo() {
	var x = 10;
  	bar();
}

function bar() {
	console.log(x);
}

foo();
bar();

์ •์  ์Šค์ฝ”ํ”„์ผ๋•Œ

  • foo()์˜ ๊ฒฐ๊ณผ๊ฐ’: 1 / bar()์˜ ๊ฒฐ๊ณผ๊ฐ’: 1

๋™์  ์Šค์ฝ”ํ”„์ผ๋•Œ

  • foo()์˜ ๊ฒฐ๊ณผ๊ฐ’: 10 / bar()์˜ ๊ฒฐ๊ณผ๊ฐ’: 1

this

this binding: ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์—์„œ ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋˜๋Š” ๋ฐฉ์‹์— ๋”ฐ๋ผ ๊ฒฐ์ •๋˜๋Š” this ์ฐธ์กฐ

์ถœ์ฒ˜: tistory - [JS] ์•Œ์ญ๋‹ฌ์ญ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ this ๋ฐ”์ธ๋”ฉ
this ๋ฐ”์ธ๋”ฉ์˜ ๊ทœ์น™

  • ๊ธฐ๋ณธ ๋ฐ”์ธ๋”ฉ
  • ์•”์‹œ์  ๋ฐ”์ธ๋”ฉ
  • ๋ช…์‹œ์  ๋ฐ”์ธ๋”ฉ
  • new ๋ฐ”์ธ๋”ฉ
  • ํ™”์‚ดํ‘œ ํ•จ์ˆ˜

๊ธฐ๋ณธ ๋ฐ”์ธ๋”ฉ

๋‹ค์Œ ๋ฐ”์ธ๋”ฉ ๊ทœ์น™๋“ค์— ํ•ด๋‹น๋˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ ๊ธฐ๋ณธ ๋ฐ”์ธ๋”ฉ์— ํ•ด๋‹นํ•˜๋ฉฐ, ๊ธฐ๋ณธ ๋ฐ”์ธ๋”ฉ์˜ ๊ฒฝ์šฐ this๋Š” ์ „์—ญ ๊ฐ์ฒด์— ๋ฐ”์ธ๋”ฉ๋œ๋‹ค. (์ฝœ๋ฐฑ ํ•จ์ˆ˜ ๋“ฑ)
(๋ธŒ๋ผ์šฐ์ €์ผ ๊ฒฝ์šฐ window / noode.js ํ™˜๊ฒฝ์ผ ๊ฒฝ์šฐ global)

function foo() {
  const a = 10;
  console.log(this); // window
  console.log(this.a); // undefined
}

foo(); 

ํ•˜์ง€๋งŒ use strict ๋ชจ๋“œ์—์„œ๋Š” ๊ธฐ๋ณธ ๋ฐ”์ธ๋”ฉ ๋Œ€์ƒ์—์„œ ์ „์—ญ ๊ฐ์ฒด๋Š” ์ œ์™ธ๋œ๋‹ค.

์•”์‹œ์  ๋ฐ”์ธ๋”ฉ

ํ•จ์ˆ˜๊ฐ€ ๊ฐ์ฒด์˜ ๋ฉ”์„œ๋“œ๋กœ์„œ ํ˜ธ์ถœ๋˜๋Š” ์ƒํ™ฉ์—์„œ this๊ฐ€ ๋ฐ”์ธ๋”ฉ ๋  ๋•Œ๋ฅผ ์˜๋ฏธํ•œ๋‹ค.
์•”์‹œ์  ๋ฐ”์ธ๋”ฉ์˜ ๊ฒฝ์šฐ this๋Š” ํ•ด๋‹น ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•œ ๊ฐ์ฒด, ์ฆ‰ ์ฝ˜ํ…์ŠคํŠธ ๊ฐ์ฒด์— ๋ฐ”์ธ๋”ฉ๋œ๋‹ค.

const foo = {
  a: 20,
  bar: function () {
    console.log(this); // foo object
    console.log(this.a); // 20
  }
}

foo.bar(); 

ํ•˜์ง€๋งŒ ํ•จ์ˆ˜์˜ ๋ ˆํผ๋Ÿฐ์Šค๋ฅผ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ์ „๋‹ฌํ•˜๋Š” ์ƒํ™ฉ์—์„œ๋Š” ์•”์‹œ์  ๋ฐ”์ธ๋”ฉ์ด ์ ์šฉ๋˜์ง€ ์•Š๋Š”๋‹ค. ์ด ๋•Œ this๋Š” ์ „์—ญ ๊ฐ์ฒด์ด๋‹ค.

setTimeout(foo.bar, 1); // ?

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

๋ช…์‹œ์  ๋ฐ”์ธ๋”ฉ์—๋Š” call(), apply(), bind()๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.
์ด๋Š” ๋ชจ๋‘ Function์˜ ํ”„๋กœํ† ํƒ€์ž… ๋ฉ”์„œ๋“œ์ด๋‹ค.

์ถœ์ฒ˜: github - JS - this๋ฅผ ๋ณ€๊ฒฝํ•˜๋Š” call(), apply(), bind()

call()

๊ตฌ๋ฌธ: func.call(thisArg[, arg1[, arg2[, โ€ฆ]]])

์˜ˆ์‹œ1) ๋‹ค๋ฅธ ๊ฐ์ฒด์˜ ๋ฉ”์„œ๋“œ ์‚ฌ์šฉํ•˜๊ธฐ

let obj1 = {
	name: 'kim',
  	sayHello () {
    	console.log(`hello ${this.name}!`);
    }
}

let obj2 = {
	name: 'park',
}

obj1.sayHello.call(obj2); // hello park!

์˜ˆ์‹œ2) ๋‹ค๋ฅธ ์ƒ์„ฑ์ž ํ•จ์ˆ˜ ๋ฉค๋ฒ„ ๊ฐ€์ ธ์˜ค๊ธฐ

const getSetMethod = function() {
	this.getName = function() {
    	return this.name;
    }
  	this.setName = function(name) {
    	this.name = name;
    }
}

class Person {
	constructor(name) {
    	this.name = name;
      	getSetMethod.call(this);
    }
}

const kim = new Person('kim');
kim.getName(); // kim
kim.setName('lee'); // lee

์˜ˆ์‹œ3) ๋‚ด๋ถ€ํ•จ์ˆ˜์˜ this๊ฐ€ ์ƒ์œ„ ์Šค์ฝ”ํ”„๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋„๋ก ๋ณ€๊ฒฝํ•˜๊ธฐ

class Person {
	constructor(name) {
    	this.name = name;
    }
  
  	greeting() {
    	function sayHello () {
    		console.log(`hello ${this.name}!`);
	    }

      	// sayHello(); // undefined ์—๋Ÿฌ
        sayHello.call(this);
    }
  
  	
}

const kim = new Person('kim');
kim.greeting();

์˜ˆ์‹œ4) this์™€ ํ•จ๊ป˜ ๋งค๊ฐœ๋ณ€์ˆ˜ ๋„˜๊ธฐ๊ธฐ

const greeting = {
	sayHello(greetingWord) {
    	return `${greetingWord} ${this.name}!`
    }
}

const person = {
	name: 'kim'
}

greeting.sayHello.call(person, "์•ˆ๋…•ํ•˜์„ธ์š”~!");
// ์•ˆ๋…•ํ•˜์„ธ์š”~! kim!

apply()

๊ตฌ๋ฌธ: func.apply(thisArg, [argsArray])

apply()๋Š” call()๊ณผ ๊ธฐ๋Šฅ์ด ๋™์ผํ•˜์ง€๋งŒ, ์ธ์ž๋ฅผ ์ „๋‹ฌํ•˜๋Š” ๋ฐฉ์‹์—์„œ๋งŒ ์ฐจ์ด๊ฐ€ ์žˆ๋‹ค.

	sayHello(greetingWord) {
    	return `${greetingWord} ${this.name}!`
    }
}

const person = {
	name: 'kim'
}

greeting.sayHello.apply(person, ["์•ˆ๋…•ํ•˜์„ธ์š”~!"]);

bind()

call()๊ณผ apply()์™€ ๊ฐ™์€ ์—ญํ• (this ๋ฐ”์ธ๋”ฉ ๊ฐ์ฒด ๋ณ€๊ฒฝ)์„ ํ•˜์ง€๋งŒ ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹Œ ์ƒˆ๋กœ์šด ํ•จ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

let obj1 = {
	name: 'kim',
  	sayHello () {
    	console.log(`hello ${this.name}!`);
    }
}

let obj2 = {
	name: 'park',
}

obj1.sayHello.call(obj2); // hello park!
const fn = obj1.sayHello.bind(obj2);
fn(); // hello park!

new ๋ฐ”์ธ๋”ฉ

์ƒ์„ฑ์ž ํ•จ์ˆ˜์—์„œ๋Š” this ํ‚ค์›Œ๋“œ๋ฅผ ํ•ด๋‹น ์ƒ์„ฑ์ž๋ฅผ ์ด์šฉํ•ด ์ƒ์„ฑํ•  ๊ฐ์ฒด์— ๋Œ€ํ•œ ์ฐธ์กฐ๋กœ ์‚ฌ์šฉํ•œ๋‹ค.

function Foo() {
  this.a = 20;
}

const foo = new Foo();

console.log(foo.a); // 20

ํ™”์‚ดํ‘œ ํ•จ์ˆ˜

ES6์— ์ถ”๊ฐ€๋œ ํ™”์‚ดํ‘œ ํ•จ์ˆ˜(Arrow Function)๋Š” this๋ฅผ ๋ฐ”์ธ๋”ฉํ•  ๋•Œ ์•ž์„œ ์„ค๋ช…ํ•œ ๊ทœ์น™๋“ค์ด ์ ์šฉ๋˜์ง€ ์•Š๊ณ , this์— ์–ดํœ˜์  ์Šค์ฝ”ํ”„(Lexical scope)๊ฐ€ ์ ์šฉ๋œ๋‹ค. ์ฆ‰, ํ™”์‚ดํ‘œ ํ•จ์ˆ˜๋ฅผ ์ •์˜ํ•˜๋Š” ์‹œ์ ์˜ ์ปจํ…์ŠคํŠธ ๊ฐ์ฒด๊ฐ€ this์— ๋ฐ”์ธ๋”ฉ๋œ๋‹ค.

const foo = {
  a: 20,
  bar: function () {
    setTimeout(() => {
      console.log(this.a);
    }, 1);
  }
}

foo.bar(); // 20

ํ—ท๊ฐˆ๋ฆฌ๋Š” ์ผ€์ด์Šค

var value = 1;

var obj = {
    value : 100,
    func1 : function(){
        this.value += 1;
        console.log("func1()'s value: " + this.value); //func1()'s value: 101

        func2 = function(){
            this.value += 1;
            console.log("func2()'s value: " + this.value); //func2()'s value: 2
        }

        func2();
    }
};

obj.func1();

func2๋„ obj์— ๋ฐ”์ธ๋”ฉ๋˜๋„๋ก ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด?
1. func2๋ฅผ ํ™”์‚ดํ‘œ ํ•จ์ˆ˜๋กœ ๋ณ€๊ฒฝํ•œ๋‹ค.

var value = 1;

var obj = {
    value : 100,
    func1 : function(){
        this.value += 1;
        console.log("func1()'s value: " + this.value); //func1()'s value: 101

        func2 = () => {
            this.value += 1;
            console.log("func2()'s value: " + this.value); //func2()'s value: 102
        }

        func2();
    }
};

obj.func1();
  1. _this ๋ณ€์ˆ˜์— this ๋จผ์ € ํ• ๋‹นํ•˜๊ธฐ
var value = 1;

var obj = {
    value : 100,
    func1 : function(){
        const _this = this;
            
        this.value += 1;
        console.log("func1()'s value: " + this.value); //func1()'s value: 101

        func2 = () => {
            this.value += 1;
            console.log("func2()'s value: " + _this.value); //func2()'s value: 102
        }

        func2();
    }
};

obj.func1();

"๋ฉ”์„œ๋“œ ํ˜ธ์ถœ ๋ฐฉ์‹์„ ์ด์šฉํ•  ๋•Œ์—๋Š” ํ™”์‚ดํ‘œ ํ•จ์ˆ˜๋ฅผ ์™œ ์“ฐ์ง€ ์•Š์•„์•ผํ• ๊นŒ?"

์ถœ์ฒ˜: mdn - ํ™”์‚ดํ‘œ ํ•จ์ˆ˜

ํ™”์‚ดํ‘œ ํ•จ์ˆ˜๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ œํ•œ์ ์ด ์žˆ๋‹ค.

  • this, arguments๋‚˜ super์— ๋Œ€ํ•œ ์ž์ฒด ๋ฐ”์ธ๋”ฉ์ด ์—†๊ณ , methods๋กœ ์‚ฌ์šฉํ•ด์„œ๋Š” ์•ˆ๋ฉ๋‹ˆ๋‹ค.
  • new.targetํ‚ค์›Œ๋“œ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.
  • ์ผ๋ฐ˜์ ์œผ๋กœ ์Šค์ฝ”ํ”„๋ฅผ ์ง€์ •ํ•  ๋•Œ ์‚ฌ์šฉํ•˜๋Š” call, apply, bind methods๋ฅผ ์ด์šฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
  • ์ƒ์„ฑ์ž(Constructor)๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
  • yield๋ฅผ ํ™”์‚ดํ‘œ ํ•จ์ˆ˜ ๋‚ด๋ถ€์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ฝ”๋“œ๊ฐ€ ์žˆ๋‹ค๊ณ  ํ•œ๋‹ค๋ฉด,
๋ฉ”์„œ๋“œ๋Š” ๊ฐ์ฒด์— ์ข…์†๋˜์–ด ๊ฐ์ฒด์˜ ๊ฐ’์„ ์ฐธ์กฐํ•ด์•ผ ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•˜์ง€๋งŒ,
ํ™”์‚ดํ‘œ ํ•จ์ˆ˜๋Š” this ๋ฐ”์ธ๋”ฉ์ด ์—†๊ณ  ๋ ‰์Šค์ปฌ ์Šค์ฝ”ํ”„๊ฐ€ ์ ์šฉ๋œ๋‹ค๋Š” ์ ์—์„œ ๋ฉ”์„œ๋“œ๋กœ ์‚ฌ์šฉํ•˜๊ธฐ์— ์ ์ ˆํ•˜์ง€ ์•Š๋‹ค๋Š” ์˜๋ฏธ์ด๋‹ค.

'use strict';

var obj = { // does not create a new scope
  i: 10,
  b: () => console.log(this.i, this),
  c: function() {
    console.log( this.i, this)
  }
}
obj.b(); // prints undefined, Window {...} (or the global object)
obj.c(); // prints 10, Object {...}

0๊ฐœ์˜ ๋Œ“๊ธ€