プリミティブ型 (数値、文字列など) は値で渡されますが、オブジェクトは不明です。どちらも値で渡される可能性があるためです (オブジェクトを保持する変数が実際にはオブジェクトへの参照であると考える場合)。 )および参照渡し(オブジェクトへの変数がオブジェクト自体を保持していると考える場合)。
結局のところどうでもいいことなのですが、慣例に沿って引数を渡す正しい方法を知りたいのです。これに関するセマンティクスを定義する JavaScript 仕様からの抜粋はありますか?
プリミティブ型 (数値、文字列など) は値で渡されますが、オブジェクトは不明です。どちらも値で渡される可能性があるためです (オブジェクトを保持する変数が実際にはオブジェクトへの参照であると考える場合)。 )および参照渡し(オブジェクトへの変数がオブジェクト自体を保持していると考える場合)。
結局のところどうでもいいことなのですが、慣例に沿って引数を渡す正しい方法を知りたいのです。これに関するセマンティクスを定義する JavaScript 仕様からの抜粋はありますか?
JavaScriptで面白いです。次の例を検討してください。
function changeStuff(a, b, c)
{
a = a * 10;
b.item = "changed";
c = {item: "changed"};
}
var num = 10;
var obj1 = {item: "unchanged"};
var obj2 = {item: "unchanged"};
changeStuff(num, obj1, obj2);
console.log(num);
console.log(obj1.item);
console.log(obj2.item);
これにより、次の出力が生成されます。
10
changed
unchanged
obj1
がまったく参照でない場合、変更しても関数の外側にはobj1.item
影響しません。obj1
num
ということ100
で、obj2.item
お読みいただければと思います"changed"
。代わりに、num
とどまり10
、obj2.item
残ります"unchanged
」。代わりに、渡されたアイテムが値渡しされているという状況です。しかし、値渡しされる項目自体が参照です。技術的には、これはcall-by-sharingと呼ばれます。
実際には、これは、パラメーター自体を ( および のようにnum
)変更しobj2
ても、パラメーターに入力された項目には影響しないことを意味します。ただし、パラメーターの内部obj1
を変更すると、それが反映されます ( の場合と同様)。
常に値渡しですが、オブジェクトの場合、変数の値は参照です。このため、オブジェクトを渡してそのメンバーを変更すると、それらの変更は関数の外部で保持されます。これにより、参照渡しのように見えます。しかし、オブジェクト変数の値を実際に変更すると、変更が持続しないことがわかり、実際には値渡しであることが証明されます。
例:
function changeObject(x) {
x = { member: "bar" };
console.log("in changeObject: " + x.member);
}
function changeMember(x) {
x.member = "bar";
console.log("in changeMember: " + x.member);
}
var x = { member: "foo" };
console.log("before changeObject: " + x.member);
changeObject(x);
console.log("after changeObject: " + x.member); /* change did not persist */
console.log("before changeMember: " + x.member);
changeMember(x);
console.log("after changeMember: " + x.member); /* change persists */
出力:
before changeObject: foo
in changeObject: bar
after changeObject: foo
before changeMember: foo
in changeMember: bar
after changeMember: bar
これらのフレーズ/概念は、JS が作成されるずっと前に最初に定義されたものであり、JavaScript のセマンティクスを正確に説明していません。それらをJSに適用しようとすると、そうでないよりも混乱が生じると思います。
したがって、「参照/値による受け渡し」にとらわれないでください。
次の点を考慮してください。
したがって、名前を付ける必要がある場合は、「ポインター渡し」と言うでしょう。JS ではポインターを処理しませんが、基礎となるエンジンは処理します。
// code
var obj = {
name: 'Fred',
num: 1
};
// illustration
'Fred'
/
/
(obj) ---- {}
\
\
1
// code
obj.name = 'George';
// illustration
'Fred'
(obj) ---- {} ----- 'George'
\
\
1
// code
obj = {};
// illustration
'Fred'
(obj) {} ----- 'George'
| \
| \
{ } 1
// code
var obj = {
text: 'Hello world!'
};
/* function parameters get their own pointer to
* the arguments that are passed in, just like any other variable */
someFunc(obj);
// illustration
(caller scope) (someFunc scope)
\ /
\ /
\ /
\ /
\ /
{ }
|
|
|
'Hello world'
いくつかの最終的なコメント:
var a = [1,2];
var b = a;
a = [];
console.log(b); // [1,2]
// doesn't work because `b` is still pointing at the original array
関数外のオブジェクトは、外部オブジェクトへの参照を与えることによって関数に渡されます。
その参照を使用してそのオブジェクトを操作すると、外部のオブジェクトが影響を受けます。ただし、関数内で別のものへの参照を指すことにした場合、参照を別のものにリダイレクトしただけなので、外部のオブジェクトにはまったく影響しませんでした。
次のように考えてください。常に値渡しです。ただし、オブジェクトの値はオブジェクト自体ではなく、そのオブジェクトへの参照です。
これは、数値を渡す例です(プリミティブ型)
function changePrimitive(val) {
// At this point there are two '10's in memory.
// Changing one won't affect the other
val = val * 10;
}
var x = 10;
changePrimitive(x);
// x === 10
オブジェクトでこれを繰り返すと、異なる結果が得られます。
function changeObject(obj) {
// At this point there are two references (x and obj) in memory,
// but these both point to the same object.
// changing the object will change the underlying object that
// x and obj both hold a reference to.
obj.val = obj.val * 10;
}
var x = { val: 10 };
changeObject(x);
// x === { val: 100 }
もう 1 つの例:
function changeObject(obj) {
// Again there are two references (x and obj) in memory,
// these both point to the same object.
// now we create a completely new object and assign it.
// obj's reference now points to the new object.
// x's reference doesn't change.
obj = { val: 100 };
}
var x = { val: 10 };
changeObject(x);
// x === { val: 10}
値および参照によるコピー、受け渡し、および比較に関する非常に詳細な説明は、「JavaScript: The Definitive Guide」ブックのこの章にあります。
参照によるオブジェクトと配列の操作のトピックを離れる前に、命名法について明確にする必要があります。
「参照渡し」というフレーズには、いくつかの意味があります。一部の読者にとって、このフレーズは、関数がその引数に新しい値を割り当て、それらの変更された値を関数の外部で表示できるようにする関数呼び出し手法を指します。これは、この本で使用されている用語ではありません。
ここでは、オブジェクト自体ではなく、オブジェクトまたは配列への参照が関数に渡されることを単純に意味します。関数は参照を使用して、オブジェクトのプロパティまたは配列の要素を変更できます。ただし、関数が参照を新しいオブジェクトまたは配列への参照で上書きする場合、その変更は関数の外では見えません。
この用語の別の意味に精通している読者は、オブジェクトと配列は値で渡されると言いたがるかもしれませんが、渡される値は実際にはオブジェクト自体ではなく参照です。
JavaScript は常に値渡しです。すべてが値型です。
オブジェクトは値であり、オブジェクトのメンバー関数は値そのものです (関数は JavaScript のファースト クラス オブジェクトであることを思い出してください)。また、JavaScript のすべてがオブジェクトであるという概念についても、これは間違っています。文字列、記号、数値、ブール値、null、および未定義はプリミティブです。
場合によっては、基本プロトタイプから継承された一部のメンバー関数とプロパティを利用できますが、これは便宜上のものに過ぎません。それ自体がオブジェクトであるという意味ではありません。参考までに以下を試してみてください。
x = "test";
console.log(x.foo);
x.foo = 12;
console.log(x.foo);
両方console.log
で、値が であることがわかりますundefined
。
JavaScript では、その値がvalue-copyによって割り当てられるか、reference-copyによって割り当てられるかは、値の型によってのみ制御されます。
プリミティブ値は常に value-copy によって割り当て/渡されます:
null
undefined
ES6
複合値は常に参照コピーによって割り当て/渡されます
例えば
var a = 2;
var b = a; // `b` is always a copy of the value in `a`
b++;
a; // 2
b; // 3
var c = [1,2,3];
var d = c; // `d` is a reference to the shared `[1,2,3]` value
d.push( 4 );
c; // [1,2,3,4]
d; // [1,2,3,4]
上記のスニペットで2
は、 はスカラー プリミティブであるためa
、その値の 1 つの初期コピーを保持しb
、値の別のコピーが割り当てられます。を変更b
しても、 の値はまったく変更されませんa
。
ただし、c
とは両方とも、複合値であるd
同じ共有値への別個の参照です。どちらも値を「所有」し[1,2,3]
ていないことに注意することが重要です。どちらも値への同等のピア参照です。したがって、いずれかの参照を使用して実際の共有値自体を変更 ( ) すると、1 つの共有値だけに影響し、両方の参照が新しく変更された値を参照します。c
d
[1,2,3]
.push(4)
array
[1,2,3,4]
var a = [1,2,3];
var b = a;
a; // [1,2,3]
b; // [1,2,3]
// later
b = [4,5,6];
a; // [1,2,3]
b; // [4,5,6]
割り当てを行うとき、まだ参照b = [4,5,6]
している場所に影響を与えるために何もしていません( )。そのためには、への参照ではなくへのポインタでなければなりませんが、JS にはそのような機能はありません!a
[1,2,3]
b
a
array
function foo(x) {
x.push( 4 );
x; // [1,2,3,4]
// later
x = [4,5,6];
x.push( 7 );
x; // [4,5,6,7]
}
var a = [1,2,3];
foo( a );
a; // [1,2,3,4] not [4,5,6,7]
引数を渡すと、参照a
のコピーが に割り当てられます。とは、同じ値を指す別個の参照です。これで、関数内で、その参照を使用して値自体を変更できます ( )。しかし、割り当てを行うとき、これは最初の参照が指している場所に影響を与えることは決してありません - まだ(現在変更された)値を指しています。a
x
x
a
[1,2,3]
push(4)
x = [4,5,6]
a
[1,2,3,4]
複合値 ( などarray
) を値のコピーで効果的に渡すには、渡された参照が元の値を指さないように、手動でコピーを作成する必要があります。例えば:
foo( a.slice() );
参照コピーで渡すことができる複合値 (オブジェクト、配列など)
function foo(wrapper) {
wrapper.a = 42;
}
var obj = {
a: 2
};
foo( obj );
obj.a; // 42
ここでobj
は、スカラー プリミティブ プロパティのラッパーとして機能しますa
。に渡されるfoo(..)
と、obj
参照のコピーが渡され、wrapper
パラメータに設定されます。これで、wrapper
参照を使用して共有オブジェクトにアクセスし、そのプロパティを更新できます。関数が終了obj.a
すると、更新された値が表示されます42
。
セマンティクス!! 具体的な定義を設定すると、同じ単語やフレーズを使用していても同じことを説明していないため、必然的に一部の回答やコメントに互換性がなくなりますが、混乱を乗り越えることが重要です (特に新しいプログラマーにとって)。
まず第一に、誰もが理解していないように見える複数のレベルの抽象化があります。第 4 世代または第 5 世代の言語を学んだ新しいプログラマーは、ポインターからポインターへのポインターによってフェーズ化されていないアセンブリーまたは C プログラマーになじみのある概念に頭を悩ませる可能性があります。参照渡しとは、単に関数パラメーター変数を使用して参照先オブジェクトを変更できることを意味するものではありません。
変数: メモリ内の特定の場所にある値を参照するシンボルの複合概念。この用語は通常、詳細を議論する際に単独で使用するには負荷がかかりすぎます。
Symbol : 変数を参照するために使用されるテキスト文字列 (つまり、変数の名前)。
値: メモリに格納され、変数のシンボルを使用して参照される特定のビット。
メモリの場所: 変数の値が格納される場所。(場所自体は、その場所に格納されている値とは別の数値で表されます。)
関数パラメータ: 関数定義で宣言された変数。関数に渡された変数を参照するために使用されます。
関数の引数: 呼び出し元によって関数に渡される関数外の変数。
オブジェクト変数: 基本的な基になる値が「オブジェクト」自体ではなく、オブジェクトの実際のデータが格納されているメモリ内の別の場所へのポインタ (メモリ位置の値) である変数。ほとんどの高世代言語では、「ポインター」の側面は、さまざまなコンテキストでの自動逆参照によって効果的に隠されています。
原始変数: 値が実際の値である変数。この概念でさえ、さまざまな言語の自動ボクシングやオブジェクトのようなコンテキストによって複雑になる可能性がありますが、一般的な考え方は、変数の値は、別のメモリ位置へのポインターではなく、変数のシンボルによって表される実際の値であるということです。
関数の引数とパラメーターは同じものではありません。また、変数の値は変数のオブジェクトではありません (すでにさまざまな人によって指摘されていますが、明らかに無視されています)。これらの区別は、正しく理解するために重要です。
値渡しまたは呼び出しによる共有 (オブジェクトの場合): 関数の引数の値は、関数のパラメーター シンボルによって参照される別のメモリ位置に COPIED されます (それがスタック上かヒープ上かに関係なく)。言い換えれば、関数パラメータは渡された引数の値のコピーを受け取りました...そして(重要)引数の値は呼び出し元の関数によって決して更新/変更/変更されません。オブジェクト変数の値はオブジェクト自体ではなく、オブジェクトへのポインターであるため、オブジェクト変数を値で渡すと、ポインターが関数パラメーター変数にコピーされることに注意してください。関数パラメーターの値は、メモリ内のまったく同じオブジェクトを指しています。オブジェクト データ自体は、関数パラメータを介して直接変更できますが、関数引数の値は決して更新されないため、同じものを指し続けます。オブジェクト全体および関数呼び出し後でも (オブジェクトのデータが変更された場合や、関数パラメーターがまったく別のオブジェクトに割り当てられた場合でも)。参照されるオブジェクトが関数のパラメーター変数を介して更新可能であるという理由だけで、関数の引数が参照によって渡されたと結論付けるのは正しくありません。
呼び出し / 参照渡し: 関数の引数の値は、対応する関数のパラメーターによって直接更新できます。それが役立つ場合、関数パラメーターは引数の効果的な「エイリアス」になります。つまり、同じメモリ位置で同じ値を効果的に参照します。関数の引数がオブジェクト変数の場合、関数のパラメーターは引き続き引数と同じオブジェクトを指すため、オブジェクトのデータを変更する機能は値渡しの場合と同じです。しかし、オブジェクト変数の場合、関数パラメータが完全に別のオブジェクトに設定されている場合、引数も同様に別のオブジェクトを指します。これは、値渡しの場合には発生しません。
JavaScript は参照渡しではありません。よく読んでみると、すべての相反する意見は値渡しの意味を誤解しており、関数パラメーターを介してオブジェクトのデータを更新する機能は「値渡し」と同義であると誤って結論付けていることがわかります。
オブジェクトのクローン/コピー: 新しいオブジェクトが作成され、元のオブジェクトのデータがコピーされます。これはディープ コピーでもシャロー コピーでもかまいませんが、ポイントは新しいオブジェクトが作成されることです。オブジェクトのコピーの作成は、値渡しとは別の概念です。一部の言語では、クラス オブジェクトと構造体 (など) を区別し、異なる型の変数を渡す場合に異なる動作をする場合があります。しかし、JavaScript は、オブジェクト変数を渡すときに、このようなことを自動的に行いません。ただし、オブジェクトの自動複製がないからといって、参照渡しにはなりません。
観察: オブザーバーがエンジンの基になるメモリを調べる方法がない場合、不変の値がコピーされるか参照が渡されるかを判断する方法はありません。
JavaScript は、基礎となるメモリ モデルに多かれ少なかれ依存しません。参照²のようなものはありません。JavaScript には値があります。2 つの変数が同じ値を保持できます(より正確には、2 つの環境レコードが同じ値をバインドできます)。変更できる唯一の値のタイプは、抽象 [[Get]] および [[Set]] 操作によるオブジェクトです。コンピュータとメモリのことを忘れてしまっても、これだけで JavaScript の動作を説明でき、仕様を理解することができます。
let a = { prop: 1 };
let b = a; // a and b hold the same value
a.prop = "test"; // The object gets mutated, can be observed through both a and b
b = { prop: 2 }; // b holds now a different value
ここで、コンピューター上で 2 つの変数が同じ値を保持する方法を自問することができます。次に、JavaScript エンジンのソース コードを調べると、エンジンが書かれた言語のプログラマーがリファレンスと呼ぶものを見つける可能性が高くなります。
したがって、実際には、JavaScript は「値渡し」であると言えますが、値は共有できます。また、JavaScript は「参照渡し」であると言えます。これは、低レベル言語のプログラマーにとって便利な論理的抽象化である可能性があります。この動作を「共有による呼び出し」と呼ぶことができます。
JavaScript には参照のようなものは存在しないため、これらはすべて間違っているわけでも、的を射ているわけでもありません。したがって、答えが検索に特に役立つとは思いません。
²仕様における参照という用語は、従来の意味での参照ではありません。これは、オブジェクトとプロパティの名前のコンテナであり、中間値です (たとえば、 にa.b
評価されReference { value = a, name = "b" }
ます)。参照という用語は、関連のないセクションの仕様にも表示されることがあります。
これを理解する私の簡単な方法は...
関数を呼び出すときは、変数自体ではなく、引数変数の内容 (参照または値) を渡します。
var var1 = 13;
var var2 = { prop: 2 };
//13 and var2's content (reference) are being passed here
foo(var1, var2);
関数内で、パラメーター変数、inVar1
およびinVar2
は、渡される内容を受け取ります。
function foo(inVar1, inVar2){
//changing contents of inVar1 and inVar2 won't affect variables outside
inVar1 = 20;
inVar2 = { prop: 7 };
}
inVar2
の参照を受け取ったので{ prop: 2 }
、オブジェクトのプロパティの値を変更できます。
function foo(inVar1, inVar2){
inVar2.prop = 7;
}
JavaScript で関数に引数を渡すことは、C でポインター値によってパラメーターを渡すことに似ています。
/*
The following C program demonstrates how arguments
to JavaScript functions are passed in a way analogous
to pass-by-pointer-value in C. The original JavaScript
test case by @Shog9 follows with the translation of
the code into C. This should make things clear to
those transitioning from C to JavaScript.
function changeStuff(num, obj1, obj2)
{
num = num * 10;
obj1.item = "changed";
obj2 = {item: "changed"};
}
var num = 10;
var obj1 = {item: "unchanged"};
var obj2 = {item: "unchanged"};
changeStuff(num, obj1, obj2);
console.log(num);
console.log(obj1.item);
console.log(obj2.item);
This produces the output:
10
changed
unchanged
*/
#include <stdio.h>
#include <stdlib.h>
struct obj {
char *item;
};
void changeStuff(int *num, struct obj *obj1, struct obj *obj2)
{
// make pointer point to a new memory location
// holding the new integer value
int *old_num = num;
num = malloc(sizeof(int));
*num = *old_num * 10;
// make property of structure pointed to by pointer
// point to the new value
obj1->item = "changed";
// make pointer point to a new memory location
// holding the new structure value
obj2 = malloc(sizeof(struct obj));
obj2->item = "changed";
free(num); // end of scope
free(obj2); // end of scope
}
int num = 10;
struct obj obj1 = { "unchanged" };
struct obj obj2 = { "unchanged" };
int main()
{
// pass pointers by value: the pointers
// will be copied into the argument list
// of the called function and the copied
// pointers will point to the same values
// as the original pointers
changeStuff(&num, &obj1, &obj2);
printf("%d\n", num);
puts(obj1.item);
puts(obj2.item);
return 0;
}
私が見つけた最も簡潔な説明は、AirBNB スタイル ガイドにありました。
プリミティブ: プリミティブ型にアクセスすると、その値を直接処理します
例えば:
var foo = 1,
bar = foo;
bar = 9;
console.log(foo, bar); // => 1, 9
Complex : 複合型にアクセスするときは、その値への参照で作業します
例えば:
var foo = [1, 2],
bar = foo;
bar[0] = 9;
console.log(foo[0], bar[0]); // => 9, 9
つまり、事実上、プリミティブ型は値によって渡され、複合型は参照によって渡されます。
低水準言語では、参照によって変数を渡したい場合、関数の作成で特定の構文を使用する必要があります。
int myAge = 14;
increaseAgeByRef(myAge);
function increaseAgeByRef(int &age) {
*age = *age + 1;
}
は&age
への参照myAge
ですが、値が必要な場合は、 を使用して参照を変換する必要があります*age
。
JavaScript は、この変換を行う高水準言語です。
したがって、オブジェクトは参照によって渡されますが、言語は参照パラメーターを値に変換します。&
関数定義で , を使用して参照渡しする必要はなく*
、関数本体で , 参照を値に変換する必要もありません。JavaScript が自動的に行います。
そのため、関数内のオブジェクトを変更しようとすると、その値を置き換えて (つまりage = {value:5}
)、変更が保持されませんが、プロパティを変更すると (つまりage.value = 5
)、変更が保持されます。
私はこれらの回答を何度も読みましたが、Barbara Liskov が呼んだ「共有による通話」の技術的定義について学ぶまで、本当に理解できませんでした
共有による呼び出しのセマンティクスは、関数内の関数引数への割り当てが呼び出し元に表示されないという点で、参照による呼び出しとは異なります (参照によるセマンティクスとは異なります)[要出典]。したがって、たとえば、変数が渡された場合、それは不可能です。呼び出し元のスコープでその変数への割り当てをシミュレートします。ただし、関数は呼び出し元と同じオブジェクトにアクセスできるため (コピーは作成されません)、オブジェクトが変更可能な場合、関数内のそれらのオブジェクトへの変更は呼び出し元に表示され、値による呼び出しとは異なるように見える場合があります。セマンティクス。関数内の変更可能なオブジェクトの変更は、オブジェクトがコピーまたは複製されないため、呼び出し元に表示されます — オブジェクトは共有されます。
つまり、パラメーター値自体にアクセスしてアクセスすると、パラメーター参照は変更可能になります。一方、パラメーターへの割り当ては評価後に消え、関数呼び出し元からアクセスできなくなります。
Underscore.jsライブラリのextendメソッドは、変更または完全に置き換えることができるパラメータとしてオブジェクトを渡したい場合に非常に便利であることがわかりました。
function replaceOrModify(aObj) {
if (modify) {
aObj.setNewValue('foo');
} else {
var newObj = new MyObject();
// _.extend(destination, *sources)
_.extend(newObj, aObj);
}
}
パスバイコピーだと思います-
引数と変数オブジェクトは、関数呼び出しの開始時に作成される実行コンテキスト中に作成されるオブジェクトであると考えてください。関数に渡される実際の値/参照は、この引数 + 変数オブジェクトに格納されます。
簡単に言えば、プリミティブ型の場合、関数呼び出しの最初に値がコピーされ、オブジェクト型の場合、参照がコピーされます。
何かが「参照渡し」であるかどうかを判断する簡単な方法は、「スワップ」関数を記述できるかどうかです。たとえば、C では、次のことができます。
void swap(int *i, int *j)
{
int t;
t = *i;
*i = *j;
*j = t;
}
JavaScript でそれと同等のことができない場合、それは「参照渡し」ではありません。
Array と Object は、この 2 つの条件に基づいて、参照渡しまたは値渡しとして渡されます。
そのオブジェクトまたは配列の値を新しいオブジェクトまたは配列で変更している場合、それは値によって渡されます。
object1 = {item: "car"};
array1=[1,2,3];
ここでは、新しいオブジェクトまたは配列を古いオブジェクトに割り当てています。古いオブジェクトのプロパティの値を変更していないため、値渡しです。
オブジェクトまたは配列のプロパティ値を変更している場合は、参照によって渡されます。
object1.key1= "car";
array1[0]=9;
ここでは、古いオブジェクトのプロパティ値を変更しています。新しいオブジェクトまたは配列を古いオブジェクトに割り当てていないため、参照渡しです。
コード
function passVar(object1, object2, number1) {
object1.key1= "laptop";
object2 = {
key2: "computer"
};
number1 = number1 + 1;
}
var object1 = {
key1: "car"
};
var object2 = {
key2: "bike"
};
var number1 = 10;
passVar(object1, object2, number1);
console.log(object1.key1);
console.log(object2.key2);
console.log(number1);
Output: -
laptop
bike
10
関数内の単純な値は関数外の値を変更しません (値によって渡されます) が、複雑な値は変更されます (参照によって渡されます)。
function willNotChange(x) {
x = 1;
}
var x = 1000;
willNotChange(x);
document.write('After function call, x = ' + x + '<br>'); // Still 1000
function willChange(y) {
y.num = 2;
}
var y = {num: 2000};
willChange(y);
document.write('After function call y.num = ' + y.num + '<br>'); // Now 2, not 2000
プリミティブは値によって渡され、オブジェクトは参照によって渡されます。これは、C、Visual Basic、Delphi などの他の言語とは大きく異なります。オブジェクトとプリミティブを正確にどのように処理するかはわかりませんが、Visual Basic と Delphi については、指定できる (そして指定する必要がある) ことを知っています。
PHP はバージョン 5 以降、同様のことを行います。すべてのオブジェクトは参照によって渡されますが、すべてのプリミティブは、アンパサンド (&) が前にある場合、参照によって渡される可能性があります。それ以外の場合、プリミティブは値によって渡されます。
したがって、JavaScript では、オブジェクト X をパラメーターを介して関数に渡すと、それは X のままです。関数内のデータを変更する場合 (または他のオブジェクトですが、それは重要ではありません)、その新しい値は関数の外部でも使用できます。関数。