Why can't I swap 2 variables in JavaScript?

Viewed 142

I am trying to swap two variables in JavaScript, but my code does not work. Can anyone tell me why?

This should return 10, 5 I think, because I already called the swap function. But instead, it returns 5, 10.

function swap(a, b) {
  var temp = a;
  a = b;
  b = temp
}

var x = 5;
var y = 10;
swap(x, y);
console.log(x, y);

4 Answers

JavaScript, like Java, is pass by reference only. This means that while your function does swap the values, the actual values of x and y in the calling scope have not been swapped. One workaround here might be to return an array of values, swapped:

function swap(a, b) {
    return [b, a];
}

var x = 5;
var y = 10;
[x, y] = swap(x, y);
console.log("x after swap = " + x);
console.log("y after swap = " + y);

Note that here the critical line is the assignment:

[x, y] = swap(x, y);

This reassigns x and y to the swapped array in one line.

You can use Destructuring assignment method:

let a = 1;
let b = 2;

[a, b] = [b, a];

a; // => 2
b; // => 1

Javascript function values aren't passed by reference, instead values get copied in a,b. So instead return values:

function swap(a, b) {
  return [b, a];
}

Later get it:

[x, y] = swap(x, y);

You can achieve this using JavaScript's objects, which passed by sharing, similar to pass by reference you may have experienced in other languages. This allows you to do a few things that are not possible with primtive values -

function ref (value) {
  return { value }
}

function deref (t) {
  return t.value
}

function set (t, value) {
  t.value = value
}

function swap (a, b) {
  const temp = deref(a)
  set(a, deref(b))
  set(b, temp)
}

const x = ref(3)
const y = ref(5)
swap(x,y)
console.log(deref(x), deref(y)) // 5 3

You can make this abstraction in any way you choose -

const box = v => [v]
const unbox = t => t[0]
const set = (t, v) => t[0] = v

function swap (a, b) {
  const temp = unbox(a)
  set(a, unbox(b))
  set(b, temp)
}

const x = box(3)
const y = box(5)
swap(x,y)
console.log(unbox(x), unbox(y)) // 5 3

Related