Skip to content

Latest commit

ย 

History

History
389 lines (297 loc) ยท 14 KB

this.md

File metadata and controls

389 lines (297 loc) ยท 14 KB

๊ฐ์ฒด๋Š” ์ƒํƒœ(state)๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ํ”„๋กœํผํ‹ฐ(Property)์™€ ๋™์ž‘(behavior)์„ ๋‚˜ํƒ€๋‚ด๋Š” ๋ฉ”์„œ๋“œ(Method)๋ฅผ ํ•˜๋‚˜์˜ ๋…ผ๋ฆฌ์  ๋‹จ์œ„๋กœ ๋ฌถ์€ ๋ณตํ•ฉ์  ์ž๋ฃŒ๊ตฌ์กฐ๋ผ ํ–ˆ์ฃ ? ์ด๋•Œ ๋ฉ”์„œ๋“œ๊ฐ€ ๋‚ด๋ถ€ ํ”„๋กœํผํ‹ฐ๋ฅผ ์ œ์–ดํ•˜๊ธฐ ์œ„ํ•ด์„  ์ž์‹ ์ด ์†ํ•œ ๊ฐ์ฒด๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ๋ฌด์–ธ๊ฐ€๊ฐ€ ์กด์žฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ €ํฌ๋Š” ์ด ๋ฌด์–ธ๊ฐ€์ธ this์— ๋Œ€ํ•ด ์•Œ์•„๋ด…๋‹ˆ๋‹ค.

this ํ‚ค์›Œ๋“œ

์ž๊ธฐ ์ฐธ์กฐ ๋ณ€์ˆ˜(self-referencing variable)๋กœ ์ž์‹ ์ด ์†ํ•œ ๊ฐ์ฒด ๋˜๋Š” ์ž์‹ ์ด ์ƒ์„ฑํ•  ์ธ์Šคํ„ด์Šค๋ฅผ ๊ฐ€๋ฆฌํ‚ต๋‹ˆ๋‹ค.

์ž ๊น ๊ฐ์ฒด ๋ฆฌํ„ฐ๋Ÿด์˜ ๊ฒฝ์šฐ๋ฅผ ์ƒ๊ฐํ•ด๋ด…์‹œ๋‹ค. ์šฐ๋ฆฌ๋Š” ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ๋‚ด๋ถ€ ๋ฉ”์„œ๋“œ๋ฅผ ์ •์˜ํ•˜๋ฉด ๋ฉ”์„œ๋“œ ๋‚ด๋ถ€์—์„œ ์ž์‹ ์ด ์†ํ•œ ๊ฐ์ฒด์˜ ์‹๋ณ„์ž๋ฅผ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

  • ๊ฐ์ฒด ๋ฆฌํ„ฐ๋Ÿด ๋ฐฉ์‹์œผ๋กœ ์„ ์–ธํ•œ ๊ฒฝ์šฐ
    const circle = {
      // ํ”„๋กœํผํ‹ฐ: ๊ฐ์ฒด ๊ณ ์œ ์˜ ์ƒํƒœ ๋ฐ์ดํ„ฐ
      radius: 5,
      // ๋ฉ”์„œ๋“œ: ์ƒํƒœ ๋ฐ์ดํ„ฐ๋ฅผ ์ฐธ์กฐํ•˜๊ณ  ์กฐ์ž‘ํ•˜๋Š” ๋™์ž‘
      getDiameter() {
        // ์ž์‹ ์ด ์†ํ•œ ๊ฐ์ฒด์ธ circle์„ ์ฐธ์กฐํ•ฉ๋‹ˆ๋‹ค.
        return 2 * circle.radius;
      }
    };
    
    console.log(circle.getDiameter()); // 10
    • getDiameter๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด circle์„ ์žฌ๊ท€์ ์œผ๋กœ ํ˜ธ์ถœํ•˜์ฃ ? ์ฆ‰, ์ด ์ฐธ์กฐ ํ‘œํ˜„์‹์ด ํ‰๊ฐ€๋˜๋Š” ์‹œ์ ์€ getDiameter ๋ฉ”์„œ๋“œ๊ฐ€ ํ˜ธ์ถœ๋˜์–ด ํ•จ์ˆ˜ ๋ชธ์ฒด๊ฐ€ ์‹คํ–‰๋˜๋Š” ์‹œ์ ์ž…๋‹ˆ๋‹ค.

๊ฐ์ฒด ๋ฆฌํ„ฐ๋Ÿด์€ ๋ณ€์ˆ˜์— ํ• ๋‹น๋˜๊ธฐ ์ „์— ํ‰๊ฐ€๋˜๋Š” ๊ฒƒ์€ ๊ณ„์† ์–ธ๊ธ‰ํ•ด์™”์ฃ ? ์ฆ‰ getDiameter๊ฐ€ ํ˜ธ์ถœ๋˜๋Š” ์‹œ์ ์—๋Š” ๊ฐ์ฒด๊ฐ€ ์ƒ์„ฑ๋œ ์‹œ์ ์ด๋ฏ€๋กœ ๋ฉ”์„œ๋“œ ๋‚ด๋ถ€์—์„œ ํ•ด๋‹น ์‹๋ณ„์ž(์œ„ ์˜ˆ์ œ์˜ ๊ฒฝ์šฐ circle)๋ฅผ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ด์ฃ . ํ•˜์ง€๋งŒ ๋‚ด๊ฐ€ ์†ํ•œ ๊ฐ์ฒด๋ฅผ ์žฌ๊ท€์ ์œผ๋กœ ์ฐธ์กฐํ•œ๋‹ค๋Š” ๊ฒƒ์€ ๋‹น์—ฐํžˆ ๊ถŒ์žฅ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

  • ์ƒ์„ฑ์ž ํ•จ์ˆ˜ ๋ฐฉ์‹์œผ๋กœ ์„ ์–ธํ•œ ๊ฒฝ์šฐ
    function Circle(radius) {
      // ์ด ์‹œ์ ์—๋Š” ์ƒ์„ฑ์ž ํ•จ์ˆ˜ ์ž์‹ ์ด ์ƒ์„ฑํ•  ์ธ์Šคํ„ด์Šค๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ์‹๋ณ„์ž๋ฅผ ์•Œ ์ˆ˜ ์—†์ฃ ?
      ????.radius = radius;
    }
    
    Circle.prototype.getDiameter = function () {
      // ์—ฌ๊ธฐ๋„ ๋งˆ์ฐฌ๊ฐ€์ง€์ž…๋‹ˆ๋‹ค.
      return 2 * ????.radius;
    };
    
    // ์ƒ์„ฑ์ž ํ•จ์ˆ˜๋กœ ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
    const circle = new Circle(5);
    • ์ƒ์„ฑ์ž ํ•จ์ˆ˜ ๋‚ด๋ถ€์—์„œ๋Š” ์ž์‹ ์ด ์ƒ์„ฑํ•œ ์ธ์Šคํ„ด์Šค๋ฅผ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ƒ์„ฑ์ž ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋˜์ง€ ์•Š๋Š” ํ•œ ์ธ์Šคํ„ด์Šค๊ฐ€ ์ƒ์„ฑ๋˜์ง€ ์•Š์ฃ .
    • ๊ฒฐ๊ตญ ์ƒ์„ฑ์ž ํ•จ์ˆ˜๋ฅผ ์ •์˜ํ•˜๋Š” ์‹œ์ ์—๋Š” ์ด ์ƒ์„ฑ์ž ํ•จ์ˆ˜๊ฐ€ ์–ด๋–ค ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•˜๋Š”์ง€, ์‹๋ณ„์ž๋Š” ๋ฌด์—‡์ธ์ง€ ์•Œ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

๊ฒฐ๊ตญ ์ž์‹ ์ด ์†ํ•œ ๊ฐ์ฒด๋‚˜ ์ƒ์„ฑํ•œ ์ธ์Šคํ„ด์Šค๋ฅผ ๊ฐ€๋ฆฌํ‚ฌ ์‹๋ณ„์ž๊ฐ€ ํ•„์š”ํ•˜๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด๊ฒŒ ๋ฐ”๋กœ this์—์š”. ์ž๊ธฐ ์ฐธ์กฐ ๋ณ€์ˆ˜(self-referencing variable)๋กœ์„œ this๋ฅผ ํ†ตํ•ด ํ•ด๋‹น ๊ฐ์ฒด๋‚˜ ์ธ์Šคํ„ด์Šค์˜ ํ”„๋กœํผํ‹ฐ์™€ ๋ฉ”์„œ๋“œ๋ฅผ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ ํŠน์ง•์€ ์•„๋ž˜์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  1. ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์—”์ง„์— ์˜ํ•ด ์•”๋ฌต์ ์œผ๋กœ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค.
  2. ๋”ฐ๋ผ์„œ ์–ด๋””์„œ๋“  ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  3. ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด arguments ๊ฐ์ฒด์™€ this๊ฐ€ ์•”๋ฌต์ ์œผ๋กœ ์ „๋‹ฌ๋ฉ๋‹ˆ๋‹ค.
  4. this๋„ ์ง€์—ญ๋ณ€์ˆ˜์ฒ˜๋Ÿผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  5. this๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” ๊ฐ’, this ๋ฐ”์ธ๋”ฉ์€ ํ•จ์ˆ˜ ํ˜ธ์ถœ ๋ฐฉ์‹์— ๋”ฐ๋ผ ๋™์ ์œผ๋กœ ๊ฒฐ์ •๋ฉ๋‹ˆ๋‹ค.

์•ž์„  ์˜ˆ์ œ๋ฅผ this๋กœ ์ˆ˜์ •ํ•ด๋ณผ๊นŒ์š”?

  • ๊ฐ์ฒด ๋ฆฌํ„ฐ๋Ÿด ๋ฐฉ์‹์œผ๋กœ ์„ ์–ธํ•œ ๊ฒฝ์šฐ

    const circle = {
      // ํ”„๋กœํผํ‹ฐ: ๊ฐ์ฒด ๊ณ ์œ ์˜ ์ƒํƒœ ๋ฐ์ดํ„ฐ
      radius: 5,
      // ๋ฉ”์„œ๋“œ: ์ƒํƒœ ๋ฐ์ดํ„ฐ๋ฅผ ์ฐธ์กฐํ•˜๊ณ  ์กฐ์ž‘ํ•˜๋Š” ๋™์ž‘
      getDiameter() {
        // ์ž์‹ ์ด ์†ํ•œ ๊ฐ์ฒด์ธ circle์„ ์ฐธ์กฐํ•ฉ๋‹ˆ๋‹ค.
        return 2 * this.radius;
      }
    };
    
    console.log(circle.getDiameter()); // 10
  • ์ƒ์„ฑ์ž ํ•จ์ˆ˜ ๋ฐฉ์‹์œผ๋กœ ์„ ์–ธํ•œ ๊ฒฝ์šฐ

    function Circle(radius) {
      // ์ด ์‹œ์ ์—๋Š” ์ƒ์„ฑ์ž ํ•จ์ˆ˜ ์ž์‹ ์ด ์ƒ์„ฑํ•  ์ธ์Šคํ„ด์Šค๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ์‹๋ณ„์ž๋ฅผ ์•Œ ์ˆ˜ ์—†์ฃ ?
      this.radius = radius;
    }
    
    Circle.prototype.getDiameter = function () {
      // ์—ฌ๊ธฐ๋„ ๋งˆ์ฐฌ๊ฐ€์ง€์ž…๋‹ˆ๋‹ค.
      return 2 * this.radius;
    };
    
    // ์ƒ์„ฑ์ž ํ•จ์ˆ˜๋กœ ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
    const circle = new Circle(5);

this ๋ฐ”์ธ๋”ฉ์ด๋ž€ ์‹๋ณ„์ž์™€ ๊ฐ’์„ ์—ฐ๊ฒฐํ•˜๋Š” ๊ณผ์ •์œผ๋กœ, this(ํ‚ค์›Œ๋“œ์ด๋‚˜ ์‹๋ณ„์ž๋กœ ๋ถ„๋ฅ˜๋ผ์š”)์™€ this๊ฐ€ ๊ฐ€๋ฆฌํ‚ฌ ๊ฐ์ฒด๋ฅผ ์—ฐ๊ฒฐํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ํด๋ž˜์Šค ๊ธฐ๋ฐ˜ ์–ธ์–ด๋Š” ์ด this๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” ๋Œ€์ƒ์ด ํด๋ž˜์Šค๊ฐ€ ์ƒ์„ฑํ•˜๋Š” ์ธ์Šคํ„ด์Šค์ด์ง€๋งŒ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋Š” ํ•จ์ˆ˜ ํ˜ธ์ถœ ๋ฐฉ์‹์— ๋”ฐ๋ผ ๋‹ค๋ฅด๋‹ค๋Š” ๊ฒƒ์„ ์œ ์˜ํ•ด์ฃผ์„ธ์š”.

strict mode๋Š” this ๋ฐ”์ธ๋”ฉ์—๋„ ์˜ํ–ฅ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์—ฌ๊ธฐ๋ฅผ ์ฐธ์กฐํ•ด์ฃผ์„ธ์š”.

this๋Š” ์ž๊ธฐ ์ฐธ์กฐ ๋ณ€์ˆ˜์ž…๋‹ˆ๋‹ค. ์ผ๋ฐ˜ ํ•จ์ˆ˜ ๋‚ด๋ถ€์—์„œ๋Š” ์‚ฌ์šฉํ•  ํ•„์š”๊ฐ€ ์—†๊ธฐ ๋–„๋ฌธ์— undefined๊ฐ€ ํ• ๋‹น๋˜๋Š”๊ฒŒ ์ •์ƒ(strict mode์ฒ˜๋Ÿผ์š”)์ด์ง€๋งŒ ๊ธฐ๋ณธ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์—”์ง„์€ ์ „์—ญ ๊ฐ์ฒด์— ๋ฐ”์ธ๋”ฉ๋œ ์ƒํƒœ์ด๋ฏ€๋กœ window๋ฅผ ์ถœ๋ ฅํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ์•„๋‘์„ธ์š”.


์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์—์„œ๋Š” ๋™์ผํ•œ ํ•จ์ˆ˜๋„ ๋‹ค์–‘ํ•œ ๋ฐฉ์‹์œผ๋กœ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•จ์ˆ˜๊ฐ€ ๋™์ผํ•œ๋ฐ ๋‹ค์–‘ํ•œ ๋ฐฉ์‹์œผ๋กœ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๋‹ค๋‹ˆ์š”...? ๋ฌด์Šจ ์ข…๋ฅ˜๊ฐ€ ์žˆ์„๊นŒ์š”? ์—ฌ๊ธฐ์„œ๋Š” ์ข…๋ฅ˜์™€ ๋ฐ”์ธ๋”ฉ์ด ์–ด๋–ป๊ฒŒ ๊ฒฐ์ •๋˜๋Š”์ง€ ์ž์„ธํžˆ ์•Œ์•„๋ด…๋‹ˆ๋‹ค.


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

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

์ž ๊น! โœ‹ ๋ ‰์‹œ์ปฌ ์Šค์ฝ”ํ”„์™€ this ๋ฐ”์ธ๋”ฉ์€ ๊ฒฐ์ • ์‹œ๊ธฐ๊ฐ€ ๋‹ฌ๋ผ์š”.

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

ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๋ฐฉ์‹๊ณผ this ๋ฐ”์ธ๋”ฉ์€ ์•„๋ž˜์ฒ˜๋Ÿผ ๋‹ค์–‘ํ•ฉ๋‹ˆ๋‹ค.

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

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

๊ธฐ๋ณธ์ ์œผ๋กœ ์ „์—ญ ๊ฐ์ฒด(global object) ์— this๊ฐ€ ๋ฐ”์ธ๋”ฉ๋ฉ๋‹ˆ๋‹ค.

์ „์—ญ ํ•จ์ˆ˜์™€ ๋‚ด๋ถ€ ํ•จ์ˆ˜ ์ƒ๊ด€ ์—†์ด ์ผ๋ฐ˜ ํ•จ์ˆ˜๋กœ ํ˜ธ์ถœํ•˜๋ฉด ํ•จ์ˆ˜ ๋‚ด๋ถ€์˜ this์—๋Š” ์ „์—ญ ๊ฐ์ฒด๊ฐ€ ๋ฐ”์ธ๋”ฉ๋ฉ๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ์ด ๋ฉ”์„œ๋“œ ๋‚ด์—์„œ ์ •์˜ํ•œ ๋‚ด๋ถ€ ํ•จ์ˆ˜๋‚˜ ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋ผ๋„ ๋™์ผํ•ฉ๋‹ˆ๋‹ค.

// 1. ์ผ๋ฐ˜ ํ•จ์ˆ˜์— ์ •์˜ํ•œ ๋‚ด๋ถ€ ํ•จ์ˆ˜
function foo() {
  console.log(this);    // window
  function bar() {
    console.log(this);  // window
  }
  "use strict";
  function bar2(){
    console.log(this);  // undefined
  }
  bar();
}
foo();

// ์ „์—ญ ๊ฐ์ฒด์˜ ํ”„๋กœํผํ‹ฐ๋กœ์„œ ํ• ๋‹น๋˜๋Š” var ํ‚ค์›Œ๋“œ
var value = 1;

// 2. ๋ฉ”์„œ๋“œ์—์„œ ์ •์˜ํ•œ ๋‚ด๋ถ€ ํ•จ์ˆ˜
const obj = {
  value: 100,
  foo() {
    console.log(this);          // {value: 100, foo: ฦ’}
    console.log(this.value);    // 100

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

    bar();
  }
};

obj.foo();

// 3. ๋ฉ”์„œ๋“œ ๋‚ด์˜ ์ฝœ๋ฐฑ ํ•จ์ˆ˜
const obj = {
  value: 100,
  foo() {
    console.log(this);          // {value: 100, foo: ฦ’}
    setTimeout(function () {
      console.log(this);        // window
      console.log(this.value);  // 1
    }, 100);
  }
};

obj.foo();

๊ฒฐ๊ตญ ์ผ๋ฐ˜ ํ•จ์ˆ˜๋กœ ํ˜ธ์ถœ๋œ ๋ชจ๋“  ํ•จ์ˆ˜(๋‚ด๋ถ€, ์ฝœ๋ฐฑ ๋“ฑ) ๋‚ด๋ถ€์˜ this๋Š” ์ „์—ญ ๊ฐ์ฒด๊ฐ€ ๋ฐ”์ธ๋”ฉ๋ฉ๋‹ˆ๋‹ค.

๋‹น์—ฐํžˆ this๊ฐ€ ์ „์—ญ ๊ฐ์ฒด์—๋งŒ ๋ฐ”์ธ๋”ฉ ๋˜๋Š” ๊ฒƒ์€ ๋ฌธ์ œ๊ฐ€ ์žˆ์œผ๋ฏ€๋กœ, ๋ฉ”์„œ๋“œ์˜ ๋‚ด๋ถ€ ํ•จ์ˆ˜๋‚˜ ์ฝœ๋ฐฑ ํ•จ์ˆ˜์˜ this ๋ฐ”์ธ๋”ฉ์„ ๋ฉ”์„œ๋“œ์˜ this์™€ ์ผ์น˜์‹œํ‚ค๊ธฐ ์œ„ํ•ด์„œ๋Š” this ์‹๋ณ„์ž๋ฅผ ๋ณ€์ˆ˜์— ํ• ๋‹นํ•˜๊ฑฐ๋‚˜ apply/call/bind ๋ฉ”์„œ๋“œ, ํ™”์‚ดํ‘œ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•ด์ฃผ์„ธ์š”.

  • this๋ฅผ ๋ณ€์ˆ˜์— ํ• ๋‹นํ•˜๊ธฐ

    var value = 1;
    
    const obj = {
      value: 100,
      foo() {
        const that = this;
    
        setTimeout(function () {
          console.log(that.value); // 100
        }, 100);
      }
    };
    
    obj.foo();
  • apply/call/bind ๋ฉ”์„œ๋“œ ์‚ฌ์šฉํ•˜๊ธฐ

    var value = 1;
    
    const obj = {
      value: 100,
      foo() {
        setTimeout(function () {
          console.log(this.value); // 100
        }.bind(this), 100);
      }
    };
    
    obj.foo();
  • ํ™”์‚ดํ‘œ ํ•จ์ˆ˜ ์‚ฌ์šฉํ•˜๊ธฐ : ํ™”์‚ดํ‘œ ํ•จ์ˆ˜์˜ this๋Š” ์ƒ์œ„ ์Šค์ฝ”ํ”„์˜ this์™€ ๋ฐ”์ธ๋”ฉ๋ฉ๋‹ˆ๋‹ค.

    var value = 1;
    
    const obj = {
      value: 100,
      value2 : this.value // 1
      foo() {
        setTimeout(() => console.log(this.value), 100); // 100
      }
    };
    
    obj.foo();

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

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

๋ฉ”์„œ๋“œ ๋‚ด๋ถ€์˜ this๋Š” ํ”„๋กœํผํ‹ฐ๋กœ ๋ฉ”์„œ๋“œ๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ๊ฐ์ฒด์™€๋Š” ๊ด€๊ณ„๊ฐ€ ์—†๊ณ , ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•œ ๊ฐ์ฒด์— ๋ฐ”์ธ๋”ฉ ๋˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

// ๋ฉ”์„œ๋“œ ๋‚ด๋ถ€์˜ this๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•œ ๊ฐ์ฒด์— ๋ฐ”์ธ๋”ฉ๋ฉ๋‹ˆ๋‹ค.
const person = {
  name: 'amy',
  getName() {
    return this.name;
  }
};

// ๋ฉ”์„œ๋“œ getName์„ ํ˜ธ์ถœํ•œ ๊ฐ์ฒด๋Š” person์ด๋ฏ€๋กœ
console.log(person.getName());        // amy

const anotherPerson = {
  name: 'james'
};

// getName ๋ฉ”์„œ๋“œ๋ฅผ anotherPerson ๊ฐ์ฒด์˜ ๋ฉ”์„œ๋“œ๋กœ ํ• ๋‹น
anotherPerson.getName = person.getName;

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

// getName ๋ฉ”์„œ๋“œ๋ฅผ ๋ณ€์ˆ˜์— ํ• ๋‹น
const getName = person.getName;

// getName ๋ฉ”์„œ๋“œ๋ฅผ ์ผ๋ฐ˜ ํ•จ์ˆ˜๋กœ ํ˜ธ์ถœ
console.log(getName());               // ''

์ผ๋ฐ˜ ํ•จ์ˆ˜๋กœ ํ˜ธ์ถœ๋œ getName ํ•จ์ˆ˜ ๋‚ด๋ถ€์˜ this.name์€ ์ „์—ญ ๊ฐ์ฒด์˜ ํ”„๋กœํผํ‹ฐ window.name๊ณผ ๊ฐ™๊ณ , ๋ธŒ๋ผ์šฐ์ €์˜ window.name์€ ๋ธŒ๋ผ์šฐ์ € ์ฐฝ์˜ ์ด๋ฆ„์„ ๋‚˜ํƒ€๋‚ด๋Š” ๋นŒํŠธ์ธ ํ”„๋กœํผํ‹ฐ์ž…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๊ธฐ๋ณธ๊ฐ’์€ ''์ด ๋ผ์š”(Node.js๋Š” undefined).


์ด๋Š” ํ”„๋กœํ† ํƒ€์ž… ๋‚ด๋ถ€์— ์‚ฌ์šฉ๋œ this ๋ฐ”์ธ๋”ฉ๋„ ๋™์ผํ•ฉ๋‹ˆ๋‹ค.

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

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

const me = new Person('amy');
console.log(me.getName());               // amy

Person.prototype.name = 'james';
console.log(Person.prototype.getName()); // james

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

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

function Circle(radius) {
  this.radius = radius;
  this.getDiameter = function () {
    return 2 * this.radius;
  };
}

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

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

๋‹จ, new ์—ฐ์‚ฐ์ž ์—†์ด ํ˜ธ์ถœํ•˜๋ฉด ์ผ๋ฐ˜ ํ•จ์ˆ˜์ด๋ฏ€๋กœ... ์–ด๋–ป๊ฒŒ ๋™์ž‘ํ•˜๊ฒŒ ๋˜๋Š”์ง„ ์˜ˆ์ƒ๋˜์‹œ์ฃ ?


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

Function.prototype์˜ ๋ฉ”์„œ๋“œ๋กœ ๋ชจ๋“  ํ•จ์ˆ˜๊ฐ€ ์ƒ์†๋ฐ›์•„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

apply, call์€ this๋กœ ์‚ฌ์šฉํ•  ๊ฐ์ฒด์™€ ์ธ์ˆ˜ ๋ฆฌ์ŠคํŠธ๋ฅผ, bind๋Š” this๋งŒ์„ ์ธ์ˆ˜๋กœ ๋ฐ›์Šต๋‹ˆ๋‹ค.

  • apply : Function.prototype.apply(thisArg[, argsArray])

    • thisArg : this๋กœ ์‚ฌ์šฉํ•  ๊ฐ์ฒด
    • argsArray : ํ•จ์ˆ˜์— ์ „๋‹ฌํ•  ์ธ์ˆ˜ ๋ฆฌ์ŠคํŠธ
  • call : Function.prototype.call(thisArg[, arg1[, arg2[, ...]]])

    • thisArg : this๋กœ ์‚ฌ์šฉํ•  ๊ฐ์ฒด
    • arg1, arg2, ... : ํ•จ์ˆ˜์— ์ „๋‹ฌํ•  ์ธ์ˆ˜ ๋ฆฌ์ŠคํŠธ
  • bind : Function.prototype.bind(thisArg)

    • thisArg : this๋กœ ์‚ฌ์šฉํ•  ๊ฐ์ฒด

์ž์„ธํ•œ ์‚ฌ์šฉ๋ฒ•์€ MDN์„ ์ฐธ๊ณ ํ•ด์ฃผ์„ธ์š”.


apply์™€ call ๋ฉ”์„œ๋“œ๋Š” ๋ณธ๋ž˜ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๊ฒƒ์ด์ง€๋งŒ, ์ฒซ ๋ฒˆ์งธ ์ธ์ˆ˜๋กœ ์ „๋‹ฌํ•œ ํŠน์ • ๊ฐ์ฒด๋ฅผ ํ˜ธ์ถœํ•œ ํ•จ์ˆ˜์˜ this์— ๋ฐ”์ธ๋”ฉํ•˜์ฃ . ์ธ์ˆ˜๋ฅผ ์ „๋‹ฌํ•˜๋Š” ๋ฐฉ์‹์ด ๋‹ค๋ฅผ ๋ฟ์ด์ง€ ๋™์ž‘ ๋ฐฉ์‹์€ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  • ๋‹ค์Œ์€ getThisBinding ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด์„œ ์ธ์ˆ˜๋กœ ์ „๋‹ฌํ•œ ๊ฐ์ฒด๋ฅผ getThisBinding ํ•จ์ˆ˜์˜ this์— ๋ฐ”์ธ๋”ฉ์‹œํ‚ค๋Š” ์ฝ”๋“œ์ž…๋‹ˆ๋‹ค.
    function getThisBinding() {
      console.log(arguments);
      return this;
    }
    
    // this๋กœ ์‚ฌ์šฉํ•  ๊ฐ์ฒด
    const thisArg = { a: 1 };
    
    // 1. apply ๋ฉ”์„œ๋“œ๋Š” ํ˜ธ์ถœํ•  ํ•จ์ˆ˜์˜ ์ธ์ˆ˜๋ฅผ ๋ฐฐ์—ด๋กœ ๋ฌถ์–ด ์ „๋‹ฌ
    console.log(getThisBinding.apply(thisArg, [1, 2, 3]));
    // Arguments(3) [1, 2, 3, callee: ฦ’, Symbol(Symbol.iterator): ฦ’]
    // {a: 1}
    
    // 2. call ๋ฉ”์„œ๋“œ๋Š” ํ˜ธ์ถœํ•  ํ•จ์ˆ˜์˜ ์ธ์ˆ˜๋ฅผ ์‰ผํ‘œ๋กœ ๊ตฌ๋ถ„ํ•œ ๋ฆฌ์ŠคํŠธ ํ˜•์‹์œผ๋กœ ์ „๋‹ฌ
    console.log(getThisBinding.call(thisArg, 1, 2, 3));
    // Arguments(3) [1, 2, 3, callee: ฦ’, Symbol(Symbol.iterator): ฦ’]
    // {a: 1}
    • ์ด๋“ค์˜ ๋Œ€ํ‘œ์ ์ธ ์šฉ๋„๋Š” ์œ ์‚ฌ ๋ฐฐ์—ด ๊ฐ์ฒด์— ๋ฐฐ์—ด ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ์ž…๋‹ˆ๋‹ค.
      // 1. arguments ๊ฐ์ฒด๋ฅผ ๋ฐฐ์—ด๋กœ ๋ณ€ํ™˜
      function convertArgsToArray() {
        console.log(arguments);
      
        // Array.prototype.slice๋ฅผ ์ธ์ˆ˜์—†์ด ํ˜ธ์ถœํ•˜๋ฉด ๋ฐฐ์—ด์˜ ๋ณต์‚ฌ๋ณธ์„ ์ƒ์„ฑ
        const arr = Array.prototype.slice.call(arguments);
        // const arr = Array.prototype.slice.apply(arguments);
        console.log(arr);
      
        return arr;
      }
      
      convertArgsToArray(1, 2, 3); // [1, 2, 3]

bind ๋ฉ”์„œ๋“œ๋Š” ๋ฉ”์„œ๋“œ์˜ this์™€ ๋ฉ”์„œ๋“œ์˜ ๋‚ด๋ถ€/์ฝœ๋ฐฑ ํ•จ์ˆ˜์˜ this๊ฐ€ ๋ถˆ์ผ์น˜ํ•˜๋Š” ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ์œ ์šฉํ•˜๊ฒŒ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

  • ๋‹ค์Œ์€ bind ๋ฉ”์„œ๋“œ๋กœ this๋ฅผ ์ผ์น˜์‹œํ‚ค๋Š” ์ฝ”๋“œ์ž…๋‹ˆ๋‹ค.
    const person = {
      name: 'amy',
      foo(callback) {
        // bind ๋ฉ”์„œ๋“œ๋กœ callback ํ•จ์ˆ˜ ๋‚ด๋ถ€์˜ this ๋ฐ”์ธ๋”ฉ ์ „๋‹ฌ
        setTimeout(callback.bind(this), 100);
      }
    };
    
    person.foo(function () {
      console.log(`Hi! ${this.name}.`); // Hi! amy.
    });