In the previous post we saw how we can simulate pointers in JavaScript using closures. When we want to create a pointer to a variable, we actually create a function that references that variable:
var x; // ... var xptr = function(val) { if (arguments.length > 0) x = val; return x; }
This scheme works, but it means duplicating the function code every time a pointer is created.
Usually you can prevent code duplication by factoring out the common code. When I considered it, my first thought was to write a function (a pointer constructor) that accepts a variable and returns a pointer to that variable. But this brings us back to the original problem of creating a pointer, since in JavaScript you don’t pass a variable to a function; you only pass its value.
What we need is actually a kind of macro — a function that more or less rewrites part of the source code. The macro would ideally inject the pointer definition shown above, with the correct variable name, whenever we need it. The closest thing to macros in JavaScript is eval(), which accepts a string and executes it as part of the current environment. We’ll just use a function that accepts a variable name and returns a script excerpt that does what we want:
function makePtr(varName) { return "(function(_val) {\n" + " if (arguments.length > 0) " + varName + " = _val;\n" + " return " + varName + ";\n" + "})"; } function swap(ptr1, ptr2) { var t = ptr1(); ptr1(ptr2()); ptr2(t); } function testit() { var x = 1, y = 2; print(x,y); swap(eval(makePtr("x")), eval(makePtr("y"))); print(x,y); } testit();
The script is identical to the original one, except that function makePtr() writes the code for us — we just need to execute the code with eval(). (Again, if you don’t have a print() function you’ll have to make one yourself).
So now we can create pointers easily. The syntax for using the pointers is still not good enough: for example, assignment doesn’t look like assignment at all. Later I’ll show a possible solution for this.