在Javascript中通过引用传递字符串

时间:2009-08-20 20:28:24

标签: javascript string pass-by-reference

我想创建一个字符串并通过引用传递它,以便我可以更改单个变量并将其传播到引用它的任何其他对象。

举个例子:

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";

我希望能够实现这一目标:

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";

为什么这不起作用?

MDC reference on strings表示指标是一个对象。

我试过这个,这不是我想要的,但非常接近:

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)

重要的一点是:

  1. 我希望能够使用指标,就像它是普通的字符串对象
  2. 我希望每个报告都引用同一个对象。

7 个答案:

答案 0 :(得分:54)

Javascript中的字符串已经“通过引用”传递 - 使用字符串调用过程不涉及复制字符串的内容。手头有两个问题:

  • 字符串是不可变的。与C ++字符串相反,一旦创建了JavaScript字符串,就无法对其进行修改。
  • 在JavaScript中,变量不是静态分配的插槽,就像在C ++中一样。在您的代码中,metric是一个标签,适用于两个完全独立的字符串变量。

这是实现您想要的一种方法,使用闭包来实现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";

答案 1 :(得分:32)

您可以将字符串包装在对象中并修改存储字符串的字段。 这与您在上一个示例中所做的类似,只需要不需要更改函数。

var metric = { str : "count" } 
metric.str = "avg";

现在metric.str将包含“avg”

答案 2 :(得分:10)

封闭?

var metric = new function() {
    var _value = "count";

    this.setValue = function(s) { _value = s; };
    this.toString = function() { return _value; };
};

// snip ...
a.ShowMe();

metric.setValue("avg");
b.ShowMe();
c.ShowMe();

或使其更具通用性和高性能:

function RefString(s) {
    this.value = s;
}

RefString.prototype.toString = function() { return this.value; }
RefString.prototype.charAt = String.prototype.charAt;

var metric = new RefString("count");

// snip ...

a.ShowMe();

metric.value = "avg";
b.ShowMe();
c.ShowMe();

如果你没有关闭所需的字符串变量,那么我认为唯一的另一种方法是修改ShowMe函数,如@John Millikin的答案或重新设计代码库。

答案 3 :(得分:3)

如果将变量作为对象传递它将起作用,因为对象在Javascript中通过引用传递。

http://sirdarckcat.blogspot.com/2007/07/passing-reference-to-javascript.html

function modifyVar(obj,newVal){
obj.value=newVal;
}
var m={value: 1};
alert(x);
modifyVar("x",321);
alert(x);

答案 4 :(得分:1)

Jsfiddle:https://jsfiddle.net/ncwhmty7/1/

字符串基元(String Literal)和String对象都是不可变的。这意味着在函数中对字符串变量内容的任何更改都与函数外部发生的任何内容完全分开。有几种方法可以解决这个问题:

<强> 1。返回修改后的函数值形成函数

function concatenateString(stringA, stringB) {
    return stringA + stringB;
}
alert(concatenateString("Hi", " there"));

<强> 2。将字符串变量转换为真实对象

function modifyVar(stringA, stringB) {
    var result = stringA + stringB;
    stringA.valueOf = stringA.toSource = stringA.toString = function() {
        return result;
    };
}
var stringA = Object('HI');
modifyVar(stringA, ' there');
alert(stringA);

答案 5 :(得分:0)

在JavaScript中,字符串是不可变的。您无法在Report实例具有句柄的情况下更改字符串本身。

您的解决方案有效,但这可能更简单:

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

var metric = {};
metric.str = "count";

a.Showme();
metric.str = "avg";
b.ShowMe();

答案 6 :(得分:0)

如果该字符串是某个对象的属性,则可以发送对象和该属性的stringKey:

    this.modificationFunction = function(object, stringKey){
      object[stringKey] = object[stringKey] + "bla bla bla";
    }

    myObject.myStringProperty = "She said: ";
    this.modificationFunction(myObject, "myStringProperty"); 
    // myObject.myStringProperty is now "She said: bla bla bla";