メモしておきます.【jsパラメータ伝達】
2381 ワード
以前、関数にオブジェクトが入ってきて、関数の内部でオブジェクトの値が変更され、外部のオブジェクトの値も変更されました.その時は大きなバグが発生しました.それから関数に入る対象は全部clone Deepで使います.このように使うと問題があると分かりました.当時はなぜ問題があるのか分かりませんでした.今日は「JavaScript高級プログラム設計」という本を読んでいる時、ちょうど関連する章節を見ました.そこで最終的な原因をしごきに来ました.
変数をコピー
まず、コピー変数から話します.js変数は基本タイプ(string、number、bollan、null、undefined、smbol)と参照タイプ(object)に分類されます.基本タイプのコピーは直接変数値をコピーします.2つの値は独立しています.相互に影響はありません.
パラメータ転送
ECMAScriptのすべての関数のパラメータは値によって伝達されます.つまり、関数の外部の値を関数内部のパラメータにコピーするのは、一つの変数から他の変数に値をコピーするのと同じです.
関数への参照は、実際には、入力されたパラメータを関数の内部でコピーし、関数の局所的な作用領域内のパラメータ変数に割り当てます.入力されたパラメータが基本タイプの場合、関数の内部修正パラメータは外部に影響しません.ただし、入力されたものが参照の種類であれば、外部のオブジェクトが変更されます.
ローカルスコープで修正したオブジェクトはグローバルスコープに反映されます.パラメータは参照によって伝達されると説明します.
実はそうではないです.もう一つの例を見ます.
全体の流れを分析します.
これにより、パラメータ伝達は値によって伝達されることを再確認した.この過程では関数内のオブジェクトパラメータの修正が関数の外部に影響する理由も説明した.
オブジェクトのコピーは参照のコピーにすぎないからです.
参照「JAVA Script高級プログラム設計」P 70
変数をコピー
まず、コピー変数から話します.js変数は基本タイプ(string、number、bollan、null、undefined、smbol)と参照タイプ(object)に分類されます.基本タイプのコピーは直接変数値をコピーします.2つの値は独立しています.相互に影響はありません.
const a = 'aaa'
let b = a
b = 'bbb'
console.log(a) // aaa
console.log(b) // bbb
ただし、参照の種類のコピーは、その参照をコピーしただけです.コピーした後に指すのは同じオブジェクトです.const a = {}
let b = a
b.name = 'name'
console.log(a) // {name: "name"}
console.log(b) // {name: "name"}
ここでbの値を修正したら、aの値もそれに応じて変化します.aとbが同じオブジェクトを指すと説明します.パラメータ転送
ECMAScriptのすべての関数のパラメータは値によって伝達されます.つまり、関数の外部の値を関数内部のパラメータにコピーするのは、一つの変数から他の変数に値をコピーするのと同じです.
関数への参照は、実際には、入力されたパラメータを関数の内部でコピーし、関数の局所的な作用領域内のパラメータ変数に割り当てます.入力されたパラメータが基本タイプの場合、関数の内部修正パラメータは外部に影響しません.ただし、入力されたものが参照の種類であれば、外部のオブジェクトが変更されます.
const a = 123
function f(a) {
a = 321
console.log(a) // 321
}
f(a)
console.log(a) // 123
関数fの内部はaの値を修正したが、関数外部の変数aは影響を受けていない.const a = {number: 123}
function f(a) {
a.number = 321
console.log(a) // {number: 321}
}
f(a)
console.log(a) // {number: 321}
着信パラメータがobjectの場合、パラメータを変更すると外部の変数aが修正されます.こうすれば、開発者が考えるだろう.ローカルスコープで修正したオブジェクトはグローバルスコープに反映されます.パラメータは参照によって伝達されると説明します.
実はそうではないです.もう一つの例を見ます.
const a = {}
function f(b) {
b.name = 'abc'
b = {}
b.name = 'cba'
}
f(a)
console.log(a) // {name: "abc"}
この例では、関数fはまずa.nameにabcの値を割り当てます.aに新しい対象を割り当てて、a.nameに値を付けます.参照によって伝達されると、f内部でパラメータaの3回の修正が外部変数aに反映されるはずである.しかし、外部変数aに初めての修正のみが反映されます.全体の流れを分析します.
const a = {} // a, 。
function f(b) { // b
b.name = 'abc' // b.name abc, a 。 a、b 。 a.name = b.name = 'abc'
b = {} // b , b 。 b a 。 , 。
b.name = 'cba' // b.name 'cba',
}
f(a) // a f
console.log(a) // {name: "abc"}
締め括りをつけるこれにより、パラメータ伝達は値によって伝達されることを再確認した.この過程では関数内のオブジェクトパラメータの修正が関数の外部に影響する理由も説明した.
オブジェクトのコピーは参照のコピーにすぎないからです.
参照