The JavaScript string replacement function loses the class object

advertisements

This question already has an answer here:

  • How to access the correct `this` inside a callback? 5 answers

When using JavaScript String replace with the optional function parameter, it loses the class object. The problem is best demonstrated in this jsfiddle containing the following code. Note that the Person object's "orig_last_name" never gets updated because the replace function isn't working with the Person object. Is there a way to pass the class to the replace function or is there maybe a better approach?

The example is trivial so I know there is an easier way to solve the sample problem but my real application needs to take a large string, find patterns to replace, and then modify the class object dynamically by inspecting the current string that is being replaced. The last part is the problem I'm having trouble with.

function Person() {
  this.full_name = "Bruce Wayne";
  this.last_name = null;
  this.orig_last_name = null;
}

Person.prototype.updateLastName = function() {
  // "this" is the Person object.
  console.log("in updateLastName()", this);
  this.last_name = this.full_name.replace(/\s+\S+$/g, this._replace_last_name);
}

Person.prototype._replace_last_name = function(s) {
  // "this" is now the Window object.
  console.log("in _replace_last_name()", this);
  this.orig_last_name = s;
  this.last_name = " Banner";
  return this.last_name;
}

var p1 = new Person();
p1.updateLastName();
console.log(p1.full_name, p1.last_name, p1.orig_last_name);


When you pass a method as a callback, the association with a specific object is not passed. You can use .bind() to solve the issue which will create a temporary stub function that is passed as the .replace() callback function and that stub function will reunite the method with your object like this:

Person.prototype.updateLastName = function() {
  // "this" is the Person object.
  console.log("in updateLastName()", this);
  this.last_name = this.full_name.replace(/\s+\S+$/g, this._replace_last_name.bind(this));
}

Working demo: http://jsfiddle.net/jfriend00/ZYsA9/