ReasonJun

javascript : this binding 본문

Frontend/Javasciprt

javascript : this binding

ReasonJun 2023. 6. 8. 13:30
728x90
// this binding
// 'this' is dynamically determined by the caller!

function Hello(name) {
  this.name = name;
  this.printName = function () {
    console.log(`My name is ${this.name}`);
  };
}

function YourName(name) {
  this.name = name;
  this.printName = function () {
    console.log(`Your name is ${this.name}`);
  };
}

const youjun = new Hello('youjun');
const neo = new YourName('neo');
youjun.printName(); // My name is youjun
neo.printName(); // Your name is neo

youjun.printName = neo.printName;
youjun.printName(); // Your name is youjun
neo.printName(); // Your name is neo

function printOnMonitor(printName) {
  printName(); // Don't know which object calls printName.
}

printOnMonitor(youjun.printName); // Your name is undefined

===> Solve this problem

To fix the issue in your code where printName is called without a defined object, you need to ensure that the printName function is invoked with the correct object as the this value. You can achieve this by using the bind() method or an arrow function. Here's how you can fix it:

 

Using bind() method:

function printOnMonitor(printName) {
  printName.bind(youjun)(); // Bind the 'youjun' object as the 'this' value
}

printOnMonitor(youjun.printName); // Output: Your name is youjun

In this example, the bind() method is used to bind the youjun object as the this value for the printName function. The bind() method returns a new function with the this value set, and then it is immediately invoked with ().

 

Using an arrow function:

function printOnMonitor(printName) {
  printName(); // The 'this' value will be inherited from the surrounding scope
}

printOnMonitor(() => youjun.printName()); // Output: Your name is youjun




function Name(name) {
  this.name = name;
  // Using the arrow function: The arrow function remembers 'this' in the lexical environment!
  // points to the this of the nearest scope outside the arrow function
  this.printName = () => {
    console.log(`My name is ${this.name}`);
  };
}

printOnMonitor(youjun.printName); // Output: My name is youjun

In this alternative approach, an arrow function is used as the argument to printOnMonitor. The arrow function explicitly calls youjun.printName(), and since arrow functions inherit the this value from the surrounding scope (lexical scope), the this value inside youjun.printName() will refer to the youjun object.

 

Either of these approaches will ensure that the printName function is called with the appropriate this value, resolving the issue of the undefined name.

 

// A normal function's 'this' is defined at the point of call.
// An arrow function's 'this' is defined in the function (lexical) scope in which it is declared.
// Lexical : The valid range in which the function can operate

const user = {
  firstName: 'you',
  lastName: 'Park',
  age: 85,
  getFullName: function () {
    return `${this.firstName} ${this.lastName}`;
  },
};

console.log(user.getFullName()); // you Park

const user1 = {
  firstName: 'you',
  lastName: 'Park',
  age: 85,
  getFullName: () => {
    return `${this.firstName} ${this.lastName}`;
  },
};

console.log(user.getFullName()); // error

function user() {
  this.firstName = 'neo'; // property
  this.lastName = 'anderson';
  return {
    firstName: 'you',
    lastName: 'Park',
    age: 85,
    getFullName: () => {
      // method
      return `${this.firstName} ${this.lastName}`;
    },
  };
}

const u = user();
console.log(u.getFullName()); // neo anderson

function user() {
    this.firstName = 'neo'; // property
    this.lastName = 'anderson';
    return {
      firstName: 'you',
      lastName: 'Park',
      age: 85,
      getFullName() {
        // method
        return `${this.firstName} ${this.lastName}`;
      },
    };
  }

const lewis = {
  firstName: 'Lewis',
  lastName: 'Yang',
};

const u = user();
console.log(u.getFullName()); // you Park
console.log(u.getFullName.call(lewis)); // Lewis Yang

const timer = {
  title: 'TIMER',
  timeout: function () {
    console.log(this.title); // TIMER
    setTimeout(function () {
      console.log(this.title); // undefined
    }, 1000);
  },
};

timer.timeout();

const timer1 = {
  title: 'TIMER',
  timeout: function () {
    console.log(this.title); // TIMER
    setTimeout(() => {
      console.log(this.title); // TIMER
    }, 1000);
  },
};

timer1.timeout();
728x90
Comments