私の2セント...これが私の理解です。(私が間違っている場合は自由に修正してください)
値渡し/参照渡しについて知っているすべてのものを捨てる時が来ました。
JavaScriptでは、値によって渡されるのか、参照によって渡されるのかは関係ありません。重要なのは、関数に渡されるパラメーターの変異と割り当てです。
わかりました、私が何を意味するか説明するために最善を尽くします。いくつかのオブジェクトがあるとします。
var object1 = {};
var object2 = {};
「代入」です...変数「object1」と「object2」に2つの個別の空のオブジェクトを割り当てました。
ここで、object1の方が好きだとしましょう...したがって、新しい変数を「割り当て」ます。
var favoriteObject = object1;
次に、何らかの理由で、オブジェクト2のほうが好きだと判断します。そのため、少しだけ再割り当てを行います。
favoriteObject = object2;
object1またはobject2には何も起こりませんでした。データはまったく変更していません。私たちが行ったのは、お気に入りのオブジェクトを再割り当てすることだけでした。object2とfavoriteObjectは両方とも同じオブジェクトに割り当てられていることを知っておくことが重要です。これらの変数のいずれかを使用して、オブジェクトを変更できます。
object2.name = 'Fred';
console.log(favoriteObject.name) // Logs Fred
favoriteObject.name = 'Joe';
console.log(object2.name); // Logs Joe
では、例えば文字列のようなプリミティブを見てみましょう
var string1 = 'Hello world';
var string2 = 'Goodbye world';
もう一度、お気に入りを選びます。
var favoriteString = string1;
FavoriteString変数とstring1変数の両方が「Hello world」に割り当てられています。では、favoriteStringを変更したい場合はどうでしょうか??? 何が起こるか???
favoriteString = 'Hello everyone';
console.log(favoriteString); // Logs 'Hello everyone'
console.log(string1); // Logs 'Hello world'
ええと....何が起こったのですか。FavoriteStringを変更してstring1を変更できませんでした...なぜですか?文字列オブジェクトを変更しなかったためです。私たちが行ったのは、favoriteString 変数を新しい文字列に "RE ASSIGN"することだけです。これは本質的にそれをstring1から切り離しました。前の例では、オブジェクトの名前を変更するときに、何も割り当てませんでした。(まあ、変数自体ではなく、...ただし、nameプロパティを新しい文字列に割り当てました。)代わりに、2つの変数と基になるオブジェクト間の接続を維持するオブジェクトを単に変更しました。(私たちは変更またはたいと思っていた場合であっても変異させる文字列オブジェクトを文字列は、実際にJavaScriptで不変であるため、我々は、ありませんでした。)自体を
次に、関数とパラメーターの受け渡しについて説明します。関数を呼び出してパラメーターを渡すと、基本的には新しい変数への「代入」が行われます。これは、単純に等号(=)記号。
これらの例を見てみましょう。
var myString = 'hello';
// Assign to a new variable (just like when you pass to a function)
var param1 = myString;
param1 = 'world'; // Re assignment
console.log(myString); // Logs 'hello'
console.log(param1); // Logs 'world'
今、同じことですが、機能付き
function myFunc(param1) {
param1 = 'world';
console.log(param1); // Logs 'world'
}
var myString = 'hello';
// Calls myFunc and assigns param1 to myString just like param1 = myString
myFunc(myString);
console.log(myString); // logs 'hello'
では、代わりにオブジェクトを使った例をいくつか挙げましょう...まず、関数なしで。
var myObject = {
firstName: 'Joe',
lastName: 'Smith'
};
// Assign to a new variable (just like when you pass to a function)
var otherObj = myObject;
// Let's mutate our object
otherObj.firstName = 'Sue'; // I guess Joe decided to be a girl
console.log(myObject.firstName); // Logs 'Sue'
console.log(otherObj.firstName); // Logs 'Sue'
// Now, let's reassign the variable
otherObj = {
firstName: 'Jack',
lastName: 'Frost'
};
// Now, otherObj and myObject are assigned to 2 very different objects
// And mutating one object has no influence on the other
console.log(myObject.firstName); // Logs 'Sue'
console.log(otherObj.firstName); // Logs 'Jack';
さて、同じことですが、関数呼び出しで
function myFunc(otherObj) {
// Let's mutate our object
otherObj.firstName = 'Sue';
console.log(otherObj.firstName); // Logs 'Sue'
// Now let's re-assign
otherObj = {
firstName: 'Jack',
lastName: 'Frost'
};
console.log(otherObj.firstName); // Logs 'Jack'
// Again, otherObj and myObject are assigned to 2 very different objects
// And mutating one object doesn't magically mutate the other
}
var myObject = {
firstName: 'Joe',
lastName: 'Smith'
};
// Calls myFunc and assigns otherObj to myObject just like otherObj = myObject
myFunc(myObject);
console.log(myObject.firstName); // Logs 'Sue', just like before
わかりました。この投稿全体を読んでおけば、JavaScriptで関数呼び出しがどのように機能するかを理解できたと思います。何かが参照によって渡されるのか、値によって渡されるのかは関係ありません...重要なのは代入とミューテーションです。
変数を関数に渡すたびに、等号(=)記号を使用した場合と同じように、パラメーター変数の名前が何であれ「割り当て」ます。
等号(=)は代入を意味することに注意してください。JavaScriptで関数にパラメーターを渡すことは代入も意味することを常に覚えておいてください。それらは同じであり、2つの変数はまったく同じ方法で接続されます(つまり、同じオブジェクトに割り当てられていると数えない限り、接続されていません)。
「変数の変更」が別の変数に影響を与えるのは、基になるオブジェクトが変更されたときのみです(この場合、変数は変更されていませんが、オブジェクト自体は変更されています)。
オブジェクトとプリミティブを区別しても意味がありません。これは、関数がなく、等号を使用して新しい変数に割り当てる場合とまったく同じように機能するためです。
唯一の問題は、関数に渡す変数の名前が関数パラメーターの名前と同じである場合です。これが発生した場合、関数内のパラメーターを、それが関数専用のまったく新しい変数であるかのように扱う必要があります(そうであるため)。
function myFunc(myString) {
// myString is private and does not affect the outer variable
myString = 'hello';
}
var myString = 'test';
myString = myString; // Does nothing, myString is still 'test';
myFunc(myString);
console.log(myString); // Logs 'test'