How do I swap two variables with a function in Javascript?
November 13, 2010 6:50 PM   Subscribe

How do I swap two variables with a function in Javascript?

Here's my code (it doesn't work):

function willItSwap() {
var d = 40, r = 50;
document.writeln("Before: d's value is: " + d + ", r's value is: " + r + "");
doSwap(d, r);
document.writeln("After: d's value is: " + d + ", r's value is: " + r);
}

function wrongSwap(x, y) {
var temp = x;
x = y;
y = temp;
}
posted by JamesJD to Computers & Internet (19 answers total) 1 user marked this as a favorite
 
Read up on pass by value vs. pass by reference.
posted by orthogonality at 6:57 PM on November 13, 2010


Javascript passes arguments by value (like most languages), so it isn't possible to write a function that does exactly what you're trying to make wrongSwap() do. (It is possible to "swap" reference-types like objects and arrays, but what you're actually doing in that case is swapping the contents of the objects, leaving the objects themselves unswapped.)

Why are you trying to do this? If this is for an actual task, you're probably not approaching it in the best way. If this is for learning or homework, you might want to look into how objects and arrays work in JS and how you can use them sort of like pointers.
posted by hattifattener at 7:00 PM on November 13, 2010


You need a tutorial on variable scope in Javascript and more advanced examples of many ways variable scope can work in Javascript.
posted by Monsieur Caution at 7:02 PM on November 13, 2010 [1 favorite]


Incidentally, it's not entirely correct that Javascript passes arguments by value. Objects are passed by reference.
posted by Monsieur Caution at 7:05 PM on November 13, 2010


Only kind of, Monsieur Caution— that's what I alluded to in my response. The value of an object variable is a reference to the object, not the object itself. You can't change a caller's variable to refer to a different object, which you could if object variables were really passed by reference. But you can alter the referenced object, and the caller will see that change.

(One subtlety which JamesJD may not want to think about right now is that variables scopes in Javascript are themselves objects. If you passed the caller's scope to swap() along with the names of two variables, it would be able to swap them.)
posted by hattifattener at 7:11 PM on November 13, 2010


Ah, I see what you mean. That's definitely more accurate, though I also agree it's probably too obscure for the OP.
posted by Monsieur Caution at 7:22 PM on November 13, 2010


Response by poster: All I want to do is to make d contain the original value of r and to make r contain the original value of d. Is it possible to accomplish this with a function? These links have proved confusing.
posted by JamesJD at 7:27 PM on November 13, 2010


Incidentally, it's not entirely correct that Javascript passes arguments by value. Objects are passed by reference

This is completely wrong. Object references in Javascript are _passed by value._

It's like saying that passing a pointer to a function in C is pass by reference -- utterly wrong.
posted by rr at 7:29 PM on November 13, 2010


This is completely wrong.

JavaScript: The Definitive Guide seems to be more aware of a common usage in which it is correct, although not preferable as a matter of technical detail.
posted by Monsieur Caution at 7:33 PM on November 13, 2010


Best answer: You can do it with a function if the values are fields of an object, like so (warning, I didn't actually try this code so it might contain a bug):


function willItSwap() {
var obj = new Object;
obj.d = 40;
obj.r = 50;
document.writeln("Before: d's value is: " + d + ", r's value is: " + r + "");
doSwap(obj);
document.writeln("After: d's value is: " + d + ", r's value is: " + r);
}

function wrongSwap(o) {
var temp = o.d;
o.d = o.r;
o.r = temp;
}


posted by axiom at 7:42 PM on November 13, 2010


Erm, it does contain two bugs; change willItSwap() to:


function willItSwap() {
var obj = new Object;
obj.d = 40;
obj.r = 50;
document.writeln("Before: d's value is: " + obj.d + ", r's value is: " + obj.r + "");
doSwap(obj);
document.writeln("After: d's value is: " + obj.d + ", r's value is: " + obj.r);
}



posted by axiom at 7:45 PM on November 13, 2010


Response by poster: That worked. Thanks for being helpful!
posted by JamesJD at 7:50 PM on November 13, 2010


Can you maybe tell us the context in which this functionality would be needed? It sounds like there's probably a much better way to solve whatever problem you're trying to solve.
posted by Rhomboid at 7:52 PM on November 13, 2010 [1 favorite]


JavaScript: The Definitive Guide seems to be more aware of a common usage in which it is correct, although not preferable as a matter of technical detail.

It is stuff like this --

Before we leave the topic of manipulating objects and arrays by reference, we need to clear up a point of nomenclature. The phrase "pass by reference" can have several meanings. To some readers, the phrase refers to a function invocation technique that allows a function to assign new values to its arguments and to have those modified values visible outside the function. This is not the way the term is used in this book. Here, we mean simply that a reference to an object or array -- not the object itself -- is passed to a function.

-- that damage the minds of Javascript programmers. If I pass a string containing an URL path to a file on a server to a function, am I passing the file by reference? No. Nor when I pass an object reference to a function -- by value -- am I passing by reference.

This specific question exactly illustrates why it is not sensible to discuss "pass by reference" in Javascript.
posted by rr at 8:07 PM on November 13, 2010


Response by poster: Rhomboid, I was just curious about it. Sorry I can't be more specific.
posted by JamesJD at 10:03 PM on November 13, 2010


How do I swap two variables with a function in Javascript?

You cheat.
function willItSwap() {
    var d = 40, r = 50;
    document.writeln("Before: d's value is: " + d + ", r's value is: " + r + "");
    eval(swap("d", "r"));
    document.writeln("After: d's value is: " + d + ", r's value is: " + r);
}

function swap(ref1, ref2) {
    return "var hold_" + ref1 + " = " + ref1 + ";\n" +
    ref1 + " = " + ref2 + ";\n" +
    ref2 + " = hold_" + ref1 + ";" ;
}
But if you ever do this in production code, expect to be mocked.
posted by flabdablet at 3:20 AM on November 14, 2010 [1 favorite]


You could also do it using a closure:
function swapFunctionFactory( val1, val2 )
{
	return function( val )
	{
		if ( val == val1 ) return val2;
		else return val1;
	}
}

function swapValues()
{
	var a = 10;
	var b = 20;
	var swapFunction = swapFunctionFactory( a, b );
	alert( "before: a = " + a + " and b = " + b );
	a = swapFunction( a );
	b = swapFunction( b );
	alert( "after: a = " + a + " and b = " + b );
}

posted by grumblebee at 7:19 AM on November 14, 2010


Having posted the above solution, I will say I agree with Rhomboid: "there's probably a much better way to solve whatever problem you're trying to solve." It IS a good question if you're just curious. If this is for production, I would step back and ask, "What am I trying to achieve?" and see if there's a better way to achieve it, rather than using hacks.
posted by grumblebee at 7:24 AM on November 14, 2010 [1 favorite]


Recent versions of Javascript allow you to do swaps (among other things) much more neatly:
function willItSwap() {
    var d = 40, r = 50;
    document.writeln("Before: d's value is: " + d + ", r's value is: " + r + "");
    [d, r] = [r, d];
    document.writeln("After: d's value is: " + d + ", r's value is: " + r);
}
This syntax is not part of ECMA-262 as yet.
posted by flabdablet at 7:03 PM on November 14, 2010


« Older Lost quote   |   Aunt Flo Newer »
This thread is closed to new comments.