52

文字列を作成して参照で渡し、単一の変数を変更して、それを参照する他のオブジェクトに伝播できるようにします。

この例を見てください:

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リファレンスは、メトリックがオブジェクトであると述べています。

私はこれを試しましたが、これは私が望んでいることではありませんが、非常に近いです:

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. 各レポートで同じオブジェクトを参照する必要があります。
4

7 に答える 7

67

Javascript の文字列はすでに「参照渡し」されています。文字列を使用してプロシージャを呼び出す場合、文字列の内容をコピーする必要はありません。次の 2 つの問題があります。

  • 文字列は不変です。C++ 文字列とは対照的に、JavaScript 文字列は一度作成すると変更できません。
  • JavaScript では、変数は C++ のように静的に割り当てられたスロットではありません。あなたのコードでmetricは、2 つの完全に別個の文字列変数に適用されるラベルです。

クロージャーを使用して の動的スコープを実装することで、目的を達成する 1 つの方法を次に示します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";
于 2009-08-20T20:36:28.377 に答える
43

文字列をオブジェクトにラップし、文字列が格納されているフィールドを変更できます。これは、関数を変更する必要がないだけで、最後の例で行っていることと似ています。

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

これで、metric.str に「avg」が含まれます

于 2009-08-20T20:34:43.123 に答える
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();

目的の文字列変数を閉じない場合は、@ John Millikinの回答のように、ShowMe関数を変更するか、コードベースを再構築する以外に方法はないと思います。

于 2009-08-20T20:32:38.993 に答える
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);
于 2009-08-20T20:36:03.963 に答える
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();
于 2009-08-20T20:35:50.703 に答える