Skip to content

Latest commit

ย 

History

History
380 lines (278 loc) ยท 11.3 KB

function-call-and-this-binding.md

File metadata and controls

380 lines (278 loc) ยท 11.3 KB

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

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

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

  • ํ•จ์ˆ˜ ํ˜ธ์ถœ ๋ฐฉ์‹์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

    1. ํ•จ์ˆ˜ ํ˜ธ์ถœ
    2. ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ
    3. ์ƒ์„ฑ์ž ํ•จ์ˆ˜ ํ˜ธ์ถœ
    4. apply / call / bind ํ˜ธ์ถœ
const foo = function () {
  console.dir(this);
};

// 1. ํ•จ์ˆ˜ ํ˜ธ์ถœ
foo();

// 2. ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ
const obj = { foo: foo };
obj.foo();

// 3. ์ƒ์„ฑ์ž ํ•จ์ˆ˜ ํ˜ธ์ถœ
const instance = new foo();

// 4. apply, call, bind ํ˜ธ์ถœ
const bar = { name: "bar" };
foo.call(bar);
foo.apply(bar);
foo.bind(bar);

๐ŸŒณ 1. ํ•จ์ˆ˜ ํ˜ธ์ถœ

  • ์ „์—ญ ๊ฐ์ฒด(GO) ๋Š” ๋ชจ๋“  ๊ฐ์ฒด์˜ ์œ ์ผํ•œ ์ตœ์ƒ์œ„ ๊ฐ์ฒด์ด๋‹ค.
  • ๋ธŒ๋ผ์šฐ์ €์—์„œ๋Š” window, ์„œ๋ฒ„์—์„œ๋Š” global ๊ฐ์ฒด๋ฅผ ๊ฐ€๋ฆฌํ‚จ๋‹ค.

  • ์ „์—ญ ๊ฐ์ฒด๋Š” ์ „์—ญ ์Šค์ฝ”ํ”„๋ฅผ ๊ฐ–๋Š” ์ „์—ญ ๋ณ€์ˆ˜๋ฅผ ํ”„๋กœํผํ‹ฐ๋กœ ๊ฐ–๊ณ  ์žˆ๋‹ค. ๊ธ€๋กœ๋ฒŒ ์˜์—ญ์—์„œ ์„ ์–ธํ•œ ํ•จ์ˆ˜๋Š” ์ „์—ญ๊ฐ์ฒด์˜ ํ”„๋กœํผํ‹ฐ๋กœ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” ์ „์—ญ ๋ณ€์ˆ˜ ๋ฉ”์„œ๋“œ์ด๋‹ค.
var ga = 'Global variable';

console.log(ga); // Global variable
console.log(window.ga); // Global variable

function foo() {
  console.log('invoked!');
}
window.foo(); // invoked!
  • const๋‚˜ let ํ‚ค์›Œ๋“œ๋กœ ์„ ์–ธ๋œ ์ „์—ญ ๋ณ€์ˆ˜๋Š” ์ „์—ญ ๊ฐ์ฒด์˜ ํ”„๋กœํผํ‹ฐ๊ฐ€ ์•„๋‹ˆ๋‹ค.

    ```javascript=

    const constVar = 'Const Global Varable';

    console.log(window.constVar); // undefined

const funcTest = function(){ console.log('function invoked!'); } window.funcTest(); // VM3802:1 Uncaught TypeError: window.funcTest is not a function window.funcTest // undefined

- **๊ธฐ๋ณธ์ ์œผ๋กœ this๋Š” ์ „์—ญ๊ฐ์ฒด์— ๋ฐ”์ธ๋”ฉ๋œ๋‹ค.**
- **๋‚ด๋ถ€ํ•จ์ˆ˜**์˜ ๊ฒฝ์šฐ์—๋„ ์ „์—ญ ๊ฐ์ฒด์— ๋ฐ”์ธ๋”ฉ๋œ๋‹ค.
```javascript
function foo() {
  console.log("foo's this: ",  this);  // window
  function bar() {
    console.log("bar's this: ", this); // window
  }
  bar();
}
foo();
  • ๋ฉ”์„œ๋“œ์˜ ๋‚ด๋ถ€ํ•จ์ˆ˜ ์ผ ๊ฒฝ์šฐ์—๋„ ์ „์—ญ ๊ฐ์ฒด์— ๋ฐ”์ธ๋”ฉ ๋œ๋‹ค.

    ```javascript

    var value = 1;

var obj = { value: 100, foo: function() { console.log("foo's this: ", this); // obj 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 } bar(); } };

obj.foo();

- **์ฝœ๋ฐฑ ํ•จ์ˆ˜** ์ผ ๋•Œ์—๋„, this๋Š” ์ „์—ญ ๊ฐ์ฒด์— ๋ฐ”์ธ๋”ฉ ๋œ๋‹ค.

```javascript
var value = 1;

var obj = {
  value: 100,
  foo: function() {
    setTimeout(function() {
      console.log("callback's this: ",  this);  // window
      console.log("callback's this.value: ",  this.value); // 1
    }, 100);
  }
};

obj.foo();
  • ํ™”์‚ดํ‘œํ•จ์ˆ˜์˜ ๊ฒฝ์šฐ์—๋Š” this๊ฐ€ ์ •์ ์œผ๋กœ ๊ฒฐ์ •๋˜๋Š”๋ฐ, ์ด ๋•Œ this๋Š” ์ƒ์œ„ ์Šค์ฝ”ํ”„์˜ this๋ฅผ ๊ฐ€๋ฆฌํ‚จ๋‹ค.
var value = 1;

var obj = {
  value: 100,
  foo: function() {
    setTimeout(() => {
      console.log("callback's this: ",  this);  // obj
      console.log("callback's this.value: ",  this.value); // 100
    }, 100);
  }
};

obj.foo();
  • ๋ช…์‹œ์ ์œผ๋กœ this๋ฅผ ๊ฒฐ์ •ํ•˜๋Š” ๋ฐฉ์‹์€, apply, call, bind ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด๋‹ค.
var value = 'global value';
undefined
var obj = {
  value: 'obj value',
  foo: function() {
    console.log("foo's this: ",  this);  // obj
    console.log("foo's this.value: ",  this.value); // obj value
    function bar(a, b) {
      console.log("bar's this: ",  this); // obj
      console.log("bar's this.value: ", this.value); // obj value
      console.log("bar's arguments: ", arguments); // Arguments(2) [1, 2, callee: ฦ’, Symbol(Symbol.iterator): ฦ’]
    }
    bar.apply(obj, [1, 2]);
    bar.call(obj, 1, 2);
    bar.bind(obj)(1, 2);
  }
};

๐ŸŒณ 2. ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ

  • ํ•จ์ˆ˜๊ฐ€ ๊ฐ์ฒด์˜ ํ”„๋กœํผํ‹ฐ์ผ ๋•Œ, ํ•จ์ˆ˜๋ฅผ ๋ฉ”์„œ๋“œ๋ผ๊ณ  ํ•œ๋‹ค.
  • ๋ฉ”์„œ๋“œ ๋‚ด๋ถ€์˜ this๋Š” ํ•ด๋‹น ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•œ ๊ฐ์ฒด์— ๋ฐ”์ธ๋”ฉ ๋œ๋‹ค.
const bear = {
  name: "bear",
  sayName: function () {
    console.log(this.name);
  },
};

const tiger = {
  name: "tiger",
};

tiger.sayName = bear.sayName;

bear.sayName(); // bear
tiger.sayName(); // tiger

  • ํ”„๋กœํ† ํƒ€์ž…์˜ ๋ฉ”์„œ๋“œ์˜ ๊ฒฝ์šฐ์—๋„, ํ•ด๋‹น ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•œ ๊ฐ์ฒด์— ๋ฐ”์ธ๋”ฉ๋œ๋‹ค.
function Person(name) {
  this.name = name;
}

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

Person.prototype.name = "Kim";
console.log(Person.prototype.getName()); // Kim

const me = new Person("Lee");
console.log(me.getName()); // Lee

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

  • ์ƒ์„ฑ์ž ํ•จ์ˆ˜๋ž€?
    • ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๋Š” ์—ญํ• 
    • ํ˜•์‹์ด ์ •ํ•ด์ ธ์žˆ์ง€ ์•Š์œผ๋ฉฐ, ๊ธฐ์กด ํ•จ์ˆ˜์— new ์—ฐ์‚ฐ์ž๋ฅผ ๋ถ™์—ฌ์„œ ํ˜ธ์ถœํ•˜๋ฉด, ํ•ด๋‹น ํ•จ์ˆ˜๋Š” ์ƒ์„ฑ์ž ํ•จ์ˆ˜๋กœ ๋™์ž‘ํ•œ๋‹ค.
    • ์ผ๋ฐ˜์ ์œผ๋กœ ์ƒ์„ฑ์ž ํ•จ์ˆ˜๋ช…์€ ์ฒซ ๋ฌธ์ž๋ฅผ ๋Œ€๋ฌธ์ž๋กœ ํ‘œ๊ธฐํ•˜์—ฌ, ์ƒ์„ฑ์ž ํ•จ์ˆ˜์ž„์„ ๋‚˜ํƒ€๋‚ธ๋‹ค.

์ƒ์„ฑ์ž ํ•จ์ˆ˜ ๋™์ž‘ ๋ฐฉ์‹

  • new ์—ฐ์‚ฐ์ž๋กœ ์ƒ์„ฑ์ž ํ•จ์ˆ˜ ํ˜ธ์ถœ ์‹œ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ˆœ์„œ๋กœ ๋™์ž‘ํ•œ๋‹ค.
    • 1. ๋นˆ ๊ฐ์ฒด ์ƒ์„ฑ ๋ฐ this ๋ฐ”์ธ๋”ฉ
      • ๋นˆ ๊ฐ์ฒด๊ฐ€ ์ƒ์„ฑ๋˜๊ณ , ์ƒ์„ฑ์ž ํ•จ์ˆ˜ ๋‚ด๋ถ€์˜ this๋Š” ์ด ๋นˆ ๊ฐ์ฒด๋ฅผ ๊ฐ€๋ฆฌํ‚จ๋‹ค.
      • ๊ฐ์ฒด์˜ __proto__๋Š” ์ž์‹ ์˜ ํ”„๋กœํ† ํƒ€์ž… ๊ฐ์ฒด๋กœ ์ƒ์„ฑ์ž ํ•จ์ˆ˜์˜ prototype object๋ฅผ ๊ฐ€๋ฆฌํ‚จ๋‹ค. ์ด ๊ฐ์ฒด๋Š” ์ƒ์„ฑ์ž ํ•จ์ˆ˜์˜ prototype ํ”„๋กœํผํ‹ฐ๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๊ณ  ์žˆ๋‹ค.
    • 2. this๋ฅผ ํ†ตํ•œ ํ”„๋กœํผํ‹ฐ ์ƒ์„ฑ
      • ๋นˆ ๊ฐ์ฒด์— ๋™์ ์œผ๋กœ ํ”„๋กœํผํ‹ฐ๋‚˜ ๋ฉ”์„œ๋“œ๋ฅผ ์ƒ์„ฑํ•œ๋‹ค. ์ด ๋•Œ, this๋Š” ์ƒˆ๋กœ ์ƒ์„ฑ๋œ ๊ฐ์ฒด๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋ฏ€๋กœ, this๋ฅผ ํ†ตํ•ด ์ƒ์„ฑํ•œ ํ”„๋กœํผํ‹ฐ์™€ ๋ฉ”์„œ๋“œ๋Š” ์ƒˆ๋กœ ์ƒ์„ฑ๋œ ๊ฐ์ฒด์— ์ถ”๊ฐ€๋œ๋‹ค.
    • 3. ์ƒ์„ฑ๋œ ๊ฐ์ฒด ๋ฐ˜ํ™˜
      • ๋ฐ˜ํ™˜๋ฌธ์ด ์—†๋Š” ๊ฒฝ์šฐ, this์— ๋ฐ”์ธ๋”ฉ๋œ ์ƒˆ๋กœ ์ƒ์„ฑํ•œ ๊ฐ์ฒด๊ฐ€ ๋ฐ˜ํ™˜๋œ๋‹ค. ๋ช…์‹œ์ ์œผ๋กœ this๋ฅผ ๋ฐ˜ํ™˜ํ•œ ๊ฒƒ๊ณผ ๊ฐ™์€ ๊ฒฐ๊ณผ์ด๋‹ค.

        function Food(name) {
        this.name = name;
        return this; // ๋ช…์‹œ์ ์œผ๋กœ this๋ฅผ ๋ฐ˜ํ™˜ํ•˜์ง€ ์•Š์•„๋„, ์ƒˆ๋กœ ์ƒ์„ฑ๋œ ๊ฐ์ฒด๊ฐ€ ๋ฐ˜ํ™˜๋œ๋‹ค.
        }
        
        const apple = new Food("apple");
        console.log(apple.name); // apple
      • ๋ฐ˜ํ™˜๋ฌธ์ด this๊ฐ€ ์•„๋‹Œ ๋‹ค๋ฅธ ๊ฐ์ฒด๋ฅผ ๋ช…์‹œ์ ์œผ๋กœ ๋ฐ˜ํ™˜ํ•œ๋‹ค๋ฉด, this๊ฐ€ ์•„๋‹Œ ํ•ด๋‹น ๊ฐ์ฒด๊ฐ€ ๋ฐ˜ํ™˜๋œ๋‹ค. ํ•ด๋‹น ํ•จ์ˆ˜๋Š” ์ƒ์„ฑ์ž ํ•จ์ˆ˜๋กœ์„œ์˜ ์—ญํ• ์„ ์ˆ˜ํ–‰ํ•˜์ง€ ๋ชปํ•œ๋‹ค.

        const lemon = { name: "lemon" };
        function Food(name) {
        this.name = name;
        return lemon;
        }
        
        const apple = new Food("apple");
        console.log(apple.name); // lemon;

๊ฐ์ฒด ๋ฆฌํ„ฐ๋Ÿด ๋ฐฉ์‹๊ณผ ์ƒ์„ฑ์ž ํ•จ์ˆ˜ ๋ฐฉ์‹์˜ ์ฐจ์ด

  • ์ƒ์„ฑ๋œ ๊ฐ์ฒด์˜ ํ”„๋กœํ† ํƒ€์ž… ๊ฐ์ฒด
    • ๊ฐ์ฒด ๋ฆฌํ„ฐ๋Ÿด ๋ฐฉ์‹ : Object.prototype

    • ์ƒ์„ฑ์ž ํ•จ์ˆ˜ ๋ฐฉ์‹ : ์ƒ์„ฑ์ž ํ•จ์ˆ˜์˜ prototype์ด ๊ฐ€๋ฆฌํ‚ค๋Š” ๊ฐ์ฒด, ์ฆ‰ Person.prototype

      ```javascript

      // ๊ฐ์ฒด ๋ฆฌํ„ฐ๋Ÿด ๋ฐฉ์‹

      var foo = {

      name: 'foo',

      gender: 'male'

      }

console.dir(foo);

// Object // gender: "male" // name: "foo" // proto: Object

// ์ƒ์„ฑ์ž ํ•จ์ˆ˜ ๋ฐฉ์‹ function Person(name, gender) { this.name = name; this.gender = gender; }

var me = new Person('Lee', 'male'); console.dir(me);

// Person // gender: "male" // name: "Lee" // proto: Object

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

```javascript
function Seat(number) {
  this.number = number;
}
// new ํ‚ค์›Œ๋“œ ์—†์ด ํ˜ธ์ถœํ•  ๊ฒฝ์šฐ, this๋Š” ์ „์—ญ ๊ฐ์ฒด์— ๋ฐ”์ธ๋”ฉ๋œ๋‹ค.
// ๋˜ํ•œ, ๋ฐ˜ํ™˜๋ฌธ์ด ์—†์œผ๋ฏ€๋กœ undefined๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ฒŒ ๋œ๋‹ค.
const myseat = Seat(1);
console.log(myseat); // undefined
console.log(window.number); // 1

์ด์ฒ˜๋Ÿผ ์ƒ์„ฑ์ž ํ•จ์ˆ˜๋ฅผ new ํ‚ค์›Œ๋“œ ์—†์ด ํ˜ธ์ถœํ•˜๊ฒŒ ๋˜๋ฉด, new ํ‚ค์›Œ๋“œ๋กœ ์ƒ์„ฑํ•œ ๊ฒƒ๊ณผ ๋‹ค๋ฅธ ๊ฒฐ๊ณผ๋ฅผ ์ดˆ๋ž˜ํ•œ๋‹ค. ๋”ฐ๋ผ์„œ ๊ทธ๋Ÿฌํ•œ ์‹ค์ˆ˜๋ฅผ ๋ฐฉ์ง€ํ•˜๊ณ ์ž Scope-Safe Constructor๋กœ ์ƒ์„ฑ์ž ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค๊ฒŒ ๋œ๋‹ค. ์ด ํŒจํ„ด์€ ๋Œ€๋ถ€๋ถ„์˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ ๊ด‘๋ฒ”์œ„ํ•˜๊ฒŒ ์‚ฌ์šฉ๋œ๋‹ค.

function Ssc(arg) {
  if (!(this instanceof arguments.callee)) {
    return new arguments.callee(arg);
  }
  this.value = arg ? arg : 0;
}

const ssc1 = new Ssc(10);
const ssc2 = Ssc(30);
console.log(ssc1.value); // 10
console.log(ssc2.value); // 30

arguments.callee๋Š” ํ•จ์ˆ˜ ๋ฐ”๋”” ๋‚ด์—์„œ ํ˜„์žฌ ์‹คํ–‰์ค‘์ธ ํ•จ์ˆ˜์˜ ์ด๋ฆ„์ด๋‹ค. this๊ฐ€ ํ˜„์žฌ ํ˜ธ์ถœ๋œ ํ•จ์ˆ˜์˜ ์ธ์Šคํ„ด์Šค๊ฐ€ ์•„๋‹ˆ๋ผ๋ฉด, new ํ‚ค์›Œ๋“œ ์—†์ด ํ˜ธ์ถœ๋œ ํ•จ์ˆ˜์ด๋‹ค. ๋”ฐ๋ผ์„œ new ํ‚ค์›Œ๋“œ์™€ ํ•จ๊ป˜ ์ƒ์„ฑ์ž ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ, ์ƒˆ๋กœ์šด ๊ฐ์ฒด์— this๊ฐ€ ๋ฐ”์ธ๋”ฉ๋œ ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋„๋ก ํ•œ๋‹ค.

๐ŸŒณ 4. apply, call, bind ํ˜ธ์ถœ

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

func.apply(thisArg, [argsArray]) func.call(thisArg[, arg1[, arg2[, ...]]])

  • apply์™€ call์€ this๋ฅผ ํŠน์ • ๊ฐ์ฒด์— ๋ฐ”์ธ๋”ฉํ•  ๋ฟ, ๋ณธ์งˆ์ ์ธ ๊ธฐ๋Šฅ์€ ํ•จ์ˆ˜ ํ˜ธ์ถœ์ด๋‹ค.

func.bind(thisArg[, arg1[, arg2[, ...]]])

  • bind ๋ฉ”์„œ๋“œ๋Š” ์ธ์ž๋กœ ๋ฐ›์€ this๊ฐ€ ๋ฐ”์ธ๋“œ๋œ ํ•จ์ˆ˜๋ฅผ ๋ฆฌํ„ดํ•œ๋‹ค. ๋”ฐ๋ผ์„œ, ํ•จ์ˆ˜ ํ˜ธ์ถœ์„ ๋”ฐ๋กœ ํ•ด์ฃผ์–ด์•ผ ํ•œ๋‹ค.
function Product(name) {
  this.name = name;
}

const mouse = {};
const monitor = {};
const keyboard = {};

Product.call(mouse, "mouse");
Product.apply(monitor, ["monitor"]);
Product.bind(keyboard)("keyboard");
console.log(mouse); // { name: 'mouse' }
console.log(monitor); // { name: 'monitor' }
console.log(keyboard); // { name: 'keyboard' }

๋ช…์‹œ์ ์œผ๋กœ this๋ฅผ ๋ฐ”์ธ๋”ฉํ•ด์ค˜์•ผ ํ•˜๋Š” ์˜ˆ์‹œ

function Relation(relation) {
  this.relation = relation;
}

Relation.prototype.func = function (callback) {
  if (typeof callback === "function") {
      // (A)
    callback(); // undefined
  }
};

const brother = new Relation("brother");

function log() {
  // (B)
  console.log(this.relation);
}

brother.func(log);

(A)๋Š” ํ”„๋กœํ† ํƒ€์ž… ๋ฉ”์„œ๋“œ ๋‚ด๋ถ€์ด๋ฏ€๋กœ this๊ฐ€ ํ•ด๋‹น ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•œ ์ธ์Šคํ„ด์Šค์ด์ง€๋งŒ, (B)๋Š” ์ผ๋ฐ˜ํ•จ์ˆ˜์ด๋ฏ€๋กœ (B)์—์„œ์˜ this๋Š” ์ „์—ญ ๊ฐ์ฒด์ด๋‹ค. ์ „์—ญ ๊ฐ์ฒด์— relation์€ ์—†์œผ๋ฏ€๋กœ, undefined๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ฒŒ ๋œ๋‹ค.

์ด๋ ‡๊ฒŒ ์ฝœ๋ฐฑ ํ•จ์ˆ˜์˜ this์— ์ฝœ๋ฐฑํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•œ ํ•จ์ˆ˜์˜ this๋ฅผ ๋ฐ”์ธ๋”ฉ ์‹œ์ผœ์ฃผ์–ด์„œ ์˜๋„ํ•œ๋Œ€๋กœ ๋™์ž‘ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•œ๋‹ค.

function Relation(relation) {
  this.relation = relation;
}

Relation.prototype.func = function (callback) {
  if (typeof callback === "function") {
    callback.bind(this)(); // brother
  }
};

const brother = new Relation("brother");

function log() {
  console.log(this.relation);
}

brother.func(log);

์ถœ์ฒ˜