|
| 1 | +'use strict'; |
| 2 | +{ |
| 3 | + // ...args: Uses the `rest` operator. |
| 4 | + // See: https://javascript.info/rest-parameters-spread-operator#rest-parameters |
| 5 | + // The returned function is bound with the `thisValue` argument through a closure. |
| 6 | + // Note that this is a simplified version of `.bind()`: it can only bind the `this` value. |
| 7 | + function bindThis(fn, thisValue) { |
| 8 | + return function(...args) { |
| 9 | + return fn.apply(thisValue, args); |
| 10 | + }; |
| 11 | + } |
| 12 | + |
| 13 | + const myDog = { |
| 14 | + name: 'Tarzan', |
| 15 | + color: 'brown', |
| 16 | + greet: function(greeting) { |
| 17 | + console.log(`${greeting}, ${this.name}!`); |
| 18 | + }, |
| 19 | + }; |
| 20 | + |
| 21 | + // Calling `greet()` directly on the `myDog` object temporarily |
| 22 | + // sets the `this` value of the `myDog.greet` function to `myDog` |
| 23 | + // (because `myDog` is the object on which the function is called). |
| 24 | + myDog.greet('Hello'); // -> Hello, Tarzan! |
| 25 | + |
| 26 | + // Create a new function that calls (using `apply`) |
| 27 | + // the `myDog.greet` function with its `this` value |
| 28 | + // always set to the `myDog` object. |
| 29 | + // Equivalent to: |
| 30 | + // const greetMyDog = myDog.greet.bind(myDog); |
| 31 | + const greetMyDog = bindThis(myDog.greet, myDog); |
| 32 | + greetMyDog('Hi there'); // -> Hi there, Tarzan! |
| 33 | + |
| 34 | + // You can pass the bound function as an argument to |
| 35 | + // another function. This function can call it directly |
| 36 | + // without needing to be aware that it is pre-bound to an object. |
| 37 | + function sayHi(greetFn) { |
| 38 | + greetFn('Hi'); |
| 39 | + } |
| 40 | + |
| 41 | + sayHi(greetMyDog); // -> Hi, Tarzan! |
| 42 | + |
| 43 | + // The following call will produce a run time error, because |
| 44 | + // the `this` value of `myDog.greet` is `undefined`. |
| 45 | + sayHi(myDog.greet); // -> TypeError: Cannot read property 'name' of undefined |
| 46 | +} |
0 commit comments