87

関数の引数として不変である変数の参照を渡すことはできますか?

例:

var x = 0;
function a(x)
{
    x++;
}
a(x);
alert(x); //Here I want to have 1 instead of 0
4

15 に答える 15

152

JavaScriptは参照によるパラメーターの受け渡しをサポートしていないため、代わりに変数をオブジェクトにする必要があります。

var x = {Value: 0};

function a(obj)
{
    obj.Value++;
}

a(x);
document.write(x.Value); //Here i want to have 1 instead of 0

この場合、xはオブジェクトへの参照です。がx関数に渡されるとa、その参照はにコピーされobjます。したがって、メモリ内の同じものを参照してくださいobjxのプロパティを変更すると、のValueプロパティにobj影響しValueますx

Javascriptは常に関数パラメータを値で渡します。これは単に言語の仕様です。両方の関数に対してローカルなスコープで作成し、変数をまったく渡さないようにすることができます。x

于 2012-04-19T15:53:56.617 に答える
19

この質問は役立つかもしれません: javascriptで参照によって変数を渡す方法は?複数の値を返すActiveX関数からデータを読み取ります

要約すると、Javascriptプリミティブ型は常に値によって渡されますが、オブジェクト内の値は参照によって渡されます(私の見落としを指摘してくれたコメント投稿者に感謝します)。したがって、これを回避するには、整数をオブジェクト内に配置する必要があります。

var myobj = {x:0};

function a(obj)
{
    obj.x++;
}

a(myobj);
alert(myobj.x); // returns 1

  

于 2012-04-19T15:52:56.603 に答える
14

私は、Cの観点からおそらくより一般的で理解しやすい(したがって、ユーザーの例の形式により適合している)ポインターを実装する少し異なる方法を見つけました。

JavaScriptでは、Cと同様に、配列変数は実際には配列への単なるポインターであるため、ポインターを宣言するのとまったく同じように配列を使用できます。このようにして、元のオブジェクトで変数に名前を付けたにもかかわらず、コード内のすべてのポインターを同じように使用できます。

また、ポインタのアドレスとポインタのアドレスにあるものを参照する2つの異なる表記法を使用することもできます。

次に例を示します(アンダースコアを使用してポインターを示します)。

var _x = [ 10 ];

function foo(_a){
    _a[0] += 10;
}

foo(_x);

console.log(_x[0]);

収量

output: 20
于 2014-01-19T21:21:55.243 に答える
8

ウィンドウオブジェクトから「x」を参照します

var x = 0;

function a(key, ref) {
    ref = ref || window;  // object reference - default window
    ref[key]++;
}

a('x');                   // string
alert(x);
于 2014-12-23T15:45:51.470 に答える
4

遅い答えですが、クロージャを使って参照によってプリミティブ値を渡す方法に出くわしました。ポインタを作成するのはかなり複雑ですが、機能します。

function ptr(get, set) {
    return { get: get, set: set };
}

function helloWorld(namePtr) {
    console.log(namePtr.get());
    namePtr.set('jack');
    console.log(namePtr.get())
}

var myName = 'joe';
var myNamePtr = ptr(
    function () { return myName; },
    function (value) { myName = value; }
);

helloWorld(myNamePtr); // joe, jack
console.log(myName); // jack

ES6では、ラムダ式を使用するようにコードを短縮できます。

var myName = 'joe';
var myNamePtr = ptr(=> myName, v => myName = v);

helloWorld(myNamePtr); // joe, jack
console.log(myName); // jack
于 2015-06-29T17:49:46.030 に答える
3

Javascriptは、多くの問題を解決するために、ポインタをミックスコズに配置する必要があります。これは、コードが未知の変数名または動的に作成された変数を参照できることを意味します。また、モジュラーコーディングとインジェクションが簡単になります。

これは、実際にcポインターに到達できる最も近いものと私が見ているものです。

jsで:

var a = 78;       // creates a var with integer value of 78 
var pointer = 'a' // note it is a string representation of the var name
eval (pointer + ' = 12'); // equivalent to: eval ('a = 12'); but changes value of a to 12

cで:

int a = 78;       // creates a var with integer value of 78 
int pointer = &a; // makes pointer  to refer to the same address mem as a
*pointer = 12;   // changes the value of a to 12
于 2016-02-21T16:45:32.963 に答える
1

JavaScriptでは、それはグローバルになります。ただし、関数は次のようになります。

function a(){
   x++;
};

はグローバルコンテキストにあるためx、関数に渡す必要はありません。

于 2012-04-19T15:53:28.557 に答える
1

JavaScriptには参照によってプリミティブを取得するためのPerlの「\」演算子がないため不可能かもしれませんが、このパターンを使用してプリミティブの「効果的なポインタ」オブジェクトを作成する方法があります。

このソリューションは、プリミティブがすでにある場合(つまり、他のコードを変更せずにオブジェクトに入れることができない場合)に最も理にかなっていますが、コードの他の部分をいじくり回すには、そのプリミティブへのポインターを渡す必要があります。その状態で; したがって、ポインタのように動作するシームレスプロキシを使用して、その状態をいじくり回すことができます。

var proxyContainer = {};

// | attaches a pointer-lookalike getter/setter pair
// | to the container object.
var connect = function(container) {
    // | primitive, can't create a reference to it anymore
    var cant_touch_this = 1337;

    // | we know where to bind our accessor/mutator
    // | so we can bind the pair to effectively behave
    // | like a pointer in most common use cases.
    Object.defineProperty(container, 'cant_touch_this', {
        'get': function() {
            return cant_touch_this;
        },                
        'set': function(val) {
            cant_touch_this = val;
        }
    });
};

// | not quite direct, but still "touchable"
var f = function(x) {
    x.cant_touch_this += 1;
};

connect(proxyContainer);

// | looks like we're just getting cant_touch_this
// | but we're actually calling the accessor.
console.log(proxyContainer.cant_touch_this);

// | looks like we're touching cant_touch_this
// | but we're actually calling the mutator.
proxyContainer.cant_touch_this = 90;

// | looks like we touched cant_touch_this
// | but we actually called a mutator which touched it for us.
console.log(proxyContainer.cant_touch_this);

f(proxyContainer);

// | we kinda did it! :)
console.log(proxyContainer.cant_touch_this);
于 2017-01-29T18:07:33.870 に答える
0

JavaScriptでは、関数を参照して変数を渡すことはできません。ただし、参照によってオブジェクトを渡すことができます。

于 2012-04-19T15:55:23.683 に答える
0

Cやポインタのある言語とは対照的に、私は考えています:

/** Javascript **/
var o = {x:10,y:20};
var o2 = {z:50,w:200};
  • 明らかにjavascriptでは、メモリ内のオブジェクトoおよびo2 アドレスにアクセスできません
  • しかし、それらのアドレスを比較することもできません:(それらを並べ替えてから二分法でアクセスする簡単な可能性はありません)

o == o2 // obviously false : not the same address in memory
o <= o2 // true !
o >= o2 // also true !!

それは大きな問題です:

  • これは、アプリケーションによって作成(割り当て)されたすべてのオブジェクトを一覧表示/管理できることを意味します。

  • その膨大なオブジェクトのリストから、これらに関するいくつかの情報を計算します(たとえば、オブジェクトがどのようにリンクされているか)。

  • ただし、特定のオブジェクトについて作成した情報を取得する場合、二分法で膨大なリストにその情報を見つけることはできません。実際のメモリアドレスの代わりに使用できるオブジェクトごとの一意の識別子はありません。

これは最終的に、JavaScriptで記述したい場合、これが大きな問題であることを意味します。

  • javascriptデバッガー/IDE
  • または特別に最適化されたガベージコレクタ
  • データ構造ドロワー/アナライザー
于 2015-10-20T23:20:52.510 に答える
0

JavaScriptは、参照によるプリミティブ型の受け渡しをサポートしていません。ただし、回避策があります。

渡す必要のあるすべての変数をオブジェクトに入れます。この場合、変数は1つだけですx。変数を渡す代わりに、変数名を文字列( 。)として渡します"x"

var variables = {x:0};
function a(x)
{
    variables[x]++;
}
a("x");
alert(variables.x);

于 2016-06-06T15:22:41.037 に答える
0

やりたいことに応じて、変数名を保存して、後で次のようにアクセスすることができます。

function toAccessMyVariable(variableName){
  alert(window[variableName]);
}

var myFavoriteNumber = 6; 

toAccessMyVariable("myFavoriteNumber");

特定の例に適用するには、次のようにします。

var x = 0;
var pointerToX = "x";

function a(variableName)
{
    window[variableName]++;
}
a(pointerToX);
alert(x); //Here I want to have 1 instead of 0
于 2017-03-05T17:43:36.210 に答える
0

ポインタ、話の終わりをサポートしていません:-(。

私はまったく新しいCのバックグラウンドを持っていますが、イベントループとスタックについて読んでいることから、どのオブジェクトも呼び出し元にできるだけ近づける必要があることを付け加えたいと思います。私は真新しいので、これは間違っている可能性があります。

ここでの多くの回答は、グローバルにすることを提案していますが、正しく読んでいると、スタックホップが増加し、ある意味で、イベントループが不必要に断片化する可能性があります(呼び出されたオブジェクトが現在実行していることによって異なります)。

また、ポインタを模倣する例は、同じことを行うための多くの点で1であり、ポインタではありません。

于 2018-12-14T16:09:29.493 に答える
0

私は最も引用された答えに同意しますが、ポインタまたはポインティングオブジェクトはいつでも変更されるべきではないため、'var'引数から、'let'、またはこの場合は'const'を使用することに注意してください。

const x = {value: 0};

function foo(obj){
  ++obj.value;
}

foo(x);
alert(x.value);
于 2022-01-03T12:03:50.343 に答える
-1

あなたの例では、実際には同じ名前の2つの変数があります。(グローバル)変数xと関数スコープ変数x。同じ名前の2つの変数をどう処理するかを選択できる場合、javascriptは関数のスコープ名を使用し、スコープ外の変数を無視するのは興味深いことです。

javascriptが常にこのように動作すると仮定するのはおそらく安全ではありません...

乾杯!

于 2015-07-06T23:00:36.783 に答える