0

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);
ravishi
  • 3,349
  • 5
  • 31
  • 40

2 Answers2

2

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/

jfriend00
  • 683,504
  • 96
  • 985
  • 979
1

When you get the reference to a method in the object, it's just a reference to the function, it's not connected to the object. When it's called, the context is determined by how it's called, so it becomes the global context.

Use the bind method to set the context for the function reference:

this.last_name = this.full_name.replace(/\s+\S+$/g, this._replace_last_name.bind(this));
Guffa
  • 687,336
  • 108
  • 737
  • 1,005