Поменяйте местами целые массивы в Javascript
Когда я пытаюсь создать функцию для замены двух массивов, исходные массивы остаются неизменными.
function swap(x, y) {
var temp = x; x = y; y = temp;
}
u=[1, 0];
v=[0, 1];
swap(u, v);
console.log(u);
console.log(v);
Это приводит к u как [1, 0] и v как [0, 1]. Значения не были изменены после вызова функции swap.
С другой стороны, если я сделаю это без вызова функции:
u=[1, 0];
v=[0, 1];
var temp = u;
u = v;
v = temp;
console.log(u);
console.log(v);
Тогда они поменялись местами правильно, с u как [0, 1] и v как [1, 0].
Я думал, что массивы Javascript передаются по ссылке, а не по значению. Я что-то здесь неправильно понимаю?
6 ответов
Они передаются по ссылке, но они также присваиваются по ссылке. Когда ты пишешь x = y
вы не модифицируете ни один из массивов, вы просто делаете локальную переменную x
ссылаются на тот же массив, что и y
,
Если вы хотите поменять содержимое массива, вы должны изменить сами массивы:
function swap(x,y) {
var temp = x.slice(0);
x.length = 0;
[].push.apply( x, y );
y.length = 0;
[].push.apply( y, temp );
}
Javascript не имеет возможности передать ссылку на u
а также v
сами переменные. Таким образом, нет назначения x
или же y
в вашем swap()
функция изменит то, что назначено u
или же v
, Javascript передает ссылку на объект, который u
а также v
держать. Таким образом, вы не можете изменить u
а также v
переменные изнутри swap()
, Вы можете изменить содержимое объекта, на который они указывают, и, таким образом, свойства объекта, u
а также v
указать можно изменить.
Так как у меня есть фон C/C++, я думаю о том, что делает Javascript при передаче объектов как "передача по указателю". Когда вы звоните swap(u, v)
что передается swap()
Функция является указателем на массив, который u
также указывает на. Итак, теперь у вас есть две переменные u
а также x
оба "указывают" на один и тот же массив. Таким образом, если вы измените этот фактический массив, то с u
указывает на тот же массив, оба увидят модификацию. Но ничего, что вы делаете внутри swap()
функция может изменить какой объект u
или же v
на самом деле указывают на.
В Javascript единственный способ изменить объект, на который указывают исходные переменные, - сделать их свойствами объекта и передать объект следующим образом:
function swap(obj, x, y) {
var temp = obj[x]; obj[x] = obj[y]; obj[y] = temp;
}
var container = {};
container.u = [1, 0];
container.v = [0, 1];
swap(container, "u", "v");
console.log(container.u);
console.log(container.v);
Если вы не возражаете переписать оба массива с нуля, вы можете скопировать все содержимое одного массива во временный, затем скопировать один массив в другой и затем скопировать содержимое временного массива обратно в первый оригинал. Это не очень эффективно, и, возможно, есть лучший способ решить исходную проблему, но это можно сделать.
function swap(x, y) {
// remove all elements from x into a temporary array
var temp = x.splice(0, x.length);
// then copy y into x
x.push.apply(x, y);
// clear y, then copy temp into it
y.length = 0;
y.push.apply(y, temp);
}
Получить терминологию по этим вопросам "ссылка / ценность" сложно, но я сделаю все возможное.
То, что у вас есть для ваших переменных Object / Array, на самом деле просто ссылки. В отличие от C++, выражение "x = y" фактически не копирует переменные объекта в новое место в памяти. Внутренне это просто копирование указателя. Язык не имеет конструкций для "автоматического воссоздания" чего-то вроде объекта или массива в новом экземпляре; если по какой-то причине вы хотите сохранить две копии массива, вам нужно явно создать его, а затем скопировать значения (т. е. = [];
или же = new Array();
или функция копирования, как = oldArray.map(...)
)
Небольшой пример кода, который может концептуально помочь. Эти же правила применяются между объектами и массивами.
a = {}; // In case you haven't seen it, this is like shorthand of "new Object();"
b = {};
c = b;
console.log(a === b); // false
console.log(b === c); // true
b.property = "hello";
console.log(c.property) // hello
Как и в Java, JavaScript является только передачей по значению. Присвоение локальных переменных в функции никогда не влияет ни на что, кроме функции.
Февраль 2022 г. Решение для замены всего содержимого массива 2.
Вы можете использовать деструктурирование для замены двух массивов:
let a = [ 1, 2, 3, 4 ];
let b = ['a','b','c','d'];
[a,b] = [b,a]; // swap
console.log(a); // ["a", "b", "c", "d"]
console.log(b); // [1, 2, 3, 4, 5]
Чтобы поменять местами 2 массива, вы можете использовать
Версия 1
let arrA = [1,2,3,4];
let arrB = ['Eve', 'Bar', 'Foo'];
let tempArr = [arrA, arrB]; // constructing new array
arrA = tempArr [1];
arrB = tempArr [0];
Версия 1 (укороченная)
let arrA = [1,2,3,4];
let arrB = ['Eve', 'Bar', 'Foo'];
// RHS : construction a new array
// LHS : destruction of array
[arrB, arrA ] = [arrA, arrB];
Версия 2 (оператор спреда)
let arrA = [1,2,3,4];
let arrB = ['Eve', 'Bar', 'Foo'];
let arrC = [...arrB]
arrB = [...arrA]
arrA = [...arrC]