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

Posted

技术标签:

【中文标题】在 Javascript 中通过引用传递字符串【英文标题】:Pass a string by reference in Javascript 【发布时间】:2010-11-21 11:19:50 【问题描述】:

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

举个例子:

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)

这里的重点:

    我希望能够像使用普通字符串对象一样使用 metric 我希望每个报表都引用同一个对象。

【问题讨论】:

【参考方案1】:

如果该字符串是某个对象的属性,您可以发送该属性的对象和 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";

【讨论】:

【参考方案2】:

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

字符串原语(字符串文字)和字符串对象都是不可变的。这意味着在函数中对字符串变量内容的任何更改都与函数外发生的任何事情完全分开。有几个选项可以克服这个问题:

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

【讨论】:

【参考方案3】:

关闭?

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 的回答或重新构建代码库。

【讨论】:

不错。但我想避免使用 setter……而且如果不手动设置它们,调用所有原生 String 的方法(如 charAt)并不能很好地扩展。【参考方案4】:

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

【讨论】:

做得很好。我最喜欢这个,因为在 Report 中,我可以在源代码中使用最少混乱的字符串,即 a().charAt(1) 比 String(a).charAt(1) 更漂亮 “闭包是一段代码,可以通过访问封闭范围的变量来引用(和传递)。”来自***.com/a/5444581/483588 这并不能证明按值传递。这只是简单地更改指标值,当然它会记录新值! var obj = a: "a" ;变量 b = obj.a;控制台日志(obj.a); // a b = "b";控制台日志(obj.a); //一个【参考方案5】:

如果您将变量作为对象传递,它将起作用,因为对象在 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);

【讨论】:

是的,这就是我最后一个示例所展示的内容。它是一个覆盖 object.toString 函数的对象。 更一般的用法是function modifyVar(parent,obj,newValue) parent[obj]=newValue; ... 使用窗口?如果没有其他父母【参考方案6】:

在 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();

【讨论】:

【参考方案7】:

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

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

现在 metric.str 将包含 "avg"

【讨论】:

现在这是我在访问此页面时所描绘的答案。它或多或少是“关闭?”的最佳简写?也在这个列表中回答。 w3schools.com/js/js_objects.asp 不是一个闭包(本身),但度量是一个像 OP 期望的对象——唯一的缺点是额外的属性引用。 JavaScript 字符串是不可变的,但度量对象是可变的,并且此度量对象以可以共享度量对象引用的方式提供了一定程度的间接性。

以上是关于在 Javascript 中通过引用传递字符串的主要内容,如果未能解决你的问题,请参考以下文章

在Java中通过引用传递字符串?

在 C++ 中通过引用和值传递字符串

在 C++ 中通过引用传递 char 的效率

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

如何在php中通过引用传递无限参数[重复]

如何在 Turbo C/C++ 中通过引用传递字符串