Pass a string by reference in Javascript

Jeff Meatball Yang picture Jeff Meatball Yang · Aug 20, 2009 · Viewed 62.3k times · Source

I want to create a string and pass it by reference such that I can change a single variable and have that propagate to any other object that references it.

Take this example:

function Report(a, b) {
    this.ShowMe = function() { alert(a + " of " + b); }
}

var metric = new String("count");
var a = new Report(metric, "a"); 
var b = new Report(metric, "b"); 
var c = new Report(metric, "c"); 
a.ShowMe();  // outputs:  "count of a";
b.ShowMe();  // outputs:  "count of b";
c.ShowMe();  // outputs:  "count of c";

I want to be able to have this happen:

var metric = new String("count");
var a = new Report(metric, "a"); 
var b = new Report(metric, "b"); 
var c = new Report(metric, "c"); 
a.ShowMe();  // outputs:  "count of a";
metric = new String("avg");
b.ShowMe();  // outputs:  "avg of b";
c.ShowMe();  // outputs:  "avg of c";

Why doesn't this work?

The MDC reference on strings says metric is an object.

I've tried this, which is not what I want, but is very close:

var metric = {toString:function(){ return "count";}};
var a = new Report(metric, "a"); 
var b = new Report(metric, "b"); 
var c = new Report(metric, "c"); 
a.ShowMe();  // outputs:  "count of a";
metric.toString = function(){ return "avg";}; // notice I had to change the function
b.ShowMe();  // outputs:  "avg of b";
c.ShowMe();  // outputs:  "avg of c";

alert(String(metric).charAt(1)); // notice I had to use the String constructor
// I want to be able to call this: 
// metric.charAt(1)

The important points here:

  1. I want to be able to use metric like it's a normal string object
  2. I want each report to reference the same object.

Answer

John Millikin picture John Millikin · Aug 20, 2009

Strings in Javascript are already passed "by reference" -- calling a procedure with a string does not involve copying the string's contents. There are two issues at hand:

  • Strings are immutable. In contrast to C++ strings, once a JavaScript string has been created it cannot be modified.
  • In JavaScript, variables are not statically assigned slots like in C++. In your code, metric is a label which applies to two entirely separate string variables.

Here's one way to achieve what you want, using closures to implement dynamic scoping of metric:

function Report(a, b) {
    this.ShowMe = function() { alert(a() + " of " + b); }
}

var metric = "count";
var metric_fnc = function() { return metric; }
var a = new Report(metric_fnc, "a"); 
var b = new Report(metric_fnc, "b"); 
a.ShowMe();  // outputs:  "count of a";
metric = "avg";
b.ShowMe();  // outputs:  "avg of b";