42

ここでは、JavaScript関数に配列を送信するための「値による」および「参照による」の受け渡しに関する多くの回答を読みました。ただし、配列を関数に送信し、元の配列を変更しないままにしておくと問題が発生します。この例は、問題を示しています。

function myFunction(someArray)
{
// any function that makes an array based on a passed array;
// someArray has two dimensions;
// I've tried copying the passed array to a new array like this (I've also used 'someArray' directly in the code);

funcArray = new Array();
funcArray = someArray;

var i = 0;

    for(i=0; i<funcArray.length; i++)
    {
    funcArray[i].reverse;
    }

return funcArray;

}

この関数の何かが元の配列を変更する必要がある理由がわかりません。

関数呼び出しが新しい配列に割り当てられている場合、この関数を呼び出すと元の配列が直接変更されます。

myArray = [["A","B","C"],["D","E","F"],["G","H","I"]];
anotherArray = new Array();

anotherArray = myFunction(myArray);
// myArray gets modified!;

.valueOf()を使用してプリミティブを送信してみました:

anotherArray = myFunction(myArray.valueOf());
// myArray gets modified!;

配列を要素ごとに、サブ要素ごとにサブ要素ごとに分割し、すべてを新しい2次元配列に割り当てようとしましたが、元の配列は変更されたままです。

また、サブ要素を文字列に結合し、処理し、配列に分割し直しましたが、元の配列は引き続き変更されます。

配列値を関数に渡して、渡された配列を変更しない方法を知っている人はいますか?

4

9 に答える 9

57

関数内にはこれがあります:

funcArray = new Array();
funcArray = someArray;

これは実際にはコピーされませんsomeArrayが、代わりにそれを参照します。そのため、元の配列が変更されます。

Array.slice()配列のいわゆる浅いコピーを作成するために使用できます。

var funcArray = someArray.slice(0);

元の配列は変更されませんが、その各要素は元の配列の対応するエントリを参照します。「ディープクローニング」の場合、これを再帰的に行う必要があります。最も効率的な方法については、次の質問で説明します。

JavaScriptでオブジェクトをディープクローンする最も効率的な方法は何ですか?

ところで、私はvar前に追加しましたfuncArray。そうすることで、グローバル変数ではなく、関数に対してローカルになります。

于 2013-01-23T23:40:47.383 に答える
9

使用できるアレイのコピーを作成します。

これを行う簡単な方法は、var clone = original.slice(0);

于 2013-01-23T23:42:15.413 に答える
3

代入の破棄についてはどうですか(ES6 +、互換性を確認してください)?素晴らしくてきれいな解決策。

function myFunction(someArray) {

  for(let i = 0; i < someArray.length; i++)
  {
    someArray[i].reverse();
  }
  
  return someArray;
}

let myArray = [["A","B","C"],["D","E","F"],["G","H","I"]];

// Using destructuring assignment.
// NOTE: We can't just use `[...myArray]` because nested arrays will still be copied by reference.
let anotherArray = myFunction([...myArray.map(nested => [...nested])]);

console.log({original: myArray, copy: anotherArray});

于 2019-02-27T19:42:57.853 に答える
3

ES6では、スプレッド構文とデストラクチャリングを使用して、引数リストで直接シャローコピーを実行できるため、元の配列を変更せずに保持できます。

以下の例を参照してください。

const arr = [1, 2, 3, 4, 5];

function timesTen([...arr]) { // [...arr] shallow copy the array
  for(let i = 0; i < arr.length; i++) {
    arr[i] *= 10; // this would usually change the reference
  }
  return arr;
}

console.log(timesTen(arr));
console.log(arr); // unaltered

于 2019-12-28T02:13:00.407 に答える
2

配列を指す変数は、その配列への参照です。配列を渡すときは、この参照をコピーしています。

で浅いコピーを作成できますslice()。完全な深さのコピーが必要な場合は、一部のオブジェクトをコピーする際の注意点に留意して、サブオブジェクトで繰り返します。

于 2013-01-23T23:41:47.767 に答える
1

オブジェクトでこれを行う必要がある場合は、この凝ったトリックを試してください...

MY_NEW_OBJECT = JSON.parse(JSON.stringify(MY_OBJECT));
于 2014-02-20T01:24:48.697 に答える
0

一般的な解決策は...

// Use the JSON parse to clone the data.
function cloneData(data) {
  // Convert the data into a string first
  var jsonString = JSON.stringify(data);

  //  Parse the string to create a new instance of the data
  return JSON.parse(jsonString);
}

// An array with data
var original = [1, 2, 3, 4];

function mutate(data) {
  // This function changes a value in the array
  data[2] = 4;
}

// Mutate clone
mutate(cloneData(original));

// Mutate original
mutate(original);

これは、オブジェクトだけでなく配列でも機能します。

ディープクローニングが必要な場合、またはタイプがわからない場合に非常に効果的です。

ディープクローニングの例...

var arrayWithObjects = [ { id: 1 }, { id: 2 }, { id: 3 } ];

function mutate(data) {
  // In this case a property of an object is changed!
  data[1].id = 4;
}

// Mutates a (DEEP) cloned version of the array
mutate(cloneData(arrayWithObjects));

console.log(arrayWithObjects[1].id) // ==> 2

警告

  • JSONパーサーを使用してクローンを作成することは、最もパフォーマンスの高いオプションではありません。

  • JSONでサポートされているデータ型のみの関数を複製しません

  • 循環参照のクローンを作成できません

于 2013-01-23T23:41:59.930 に答える
0

オブジェクトと配列を除くJavaScriptのデフォルトでは、すべてが値によるコピーですが、配列に値によるコピーを使用する場合は、[yourArray] .slice(0)を使用し、オブジェクトにはObject.assign(target、。 ..ソース)

于 2019-12-23T09:30:27.247 に答える
-1
var aArray = [0.0, 1.0, 2.0];
var aArrayCopy = aArray.concat();
aArrayCopy[0] = "A changed value.";
console.log("aArray: "+aArray[0]+", "+aArray[1]+", "+aArray[2]);
console.log("aArrayCopy: "+aArrayCopy[0]+", "+aArrayCopy[1]+", "+aArrayCopy[2]);

この回答は編集されました。最初はnewオペレーターが解決策を処理したと述べましたが、すぐにそのエラーを認識しました。代わりに、concat()メソッドを使用してコピーを作成することを選択しました。元の回答には配列全体が表示されていなかったため、エラーが誤って隠されていました。以下に示す新しい出力は、この回答が期待どおりに機能することを証明します。

aArray: 0, 1, 2
aArrayCopy: A changed value., 1, 2
于 2017-09-25T22:19:00.490 に答える