Wednesday, April 27, 2016

When do two variables refer to the same object, and how to copy a variable

One of my greatest confusions of JavaScript (and sometimes, greatest vexation) is when two variables refer to the same object. For example, ab, but c is not the same object as d here:
var a = b = [1, 2, 3];
a.shift();                     // 1
b;                             // [2, 3]
var c = d = "Hello, World!";
c = c.slice(0, -1);            // "Hello, World"
d;                             // "Hello, World!"
Here is the rule: when assigning one variable to another, the variables refer to the same object if and only if the object is not a primitive. So, if the object is a string, boolean, or number, they do NOT refer to the same object. Otherwise, they refer to the same object.

Overcoming variable reference with clones!

So, what can be done? What if I want to copy an object? I use a trick for Arrays all the time, inline in code: array.slice() returns a new copy of array, so that you can modify it without affecting the original. For objects, this is rather intuitive: iterate over each property and put it in a new object. So here's some code for a JavaScript "clone" method:
function clone(value){
	// throw an error for undefined input
	if(typeof value === "undefined")
		throw new ReferenceError("expected argument at 0: value from {clone}");
	
	// check for primitives
	if(typeof value === "number" ||
	   typeof value === "string" ||
	   typeof value === "boolean")
	   return value;	// nothing needs to be done
	
	// check for array/sliceable objects
	if(typeof value.slice !== "undefined")
		return value.slice();
	
	// otherwise, let's iterate through the object
	var retObj = {};
	for(var prop in value){
		retObj[prop] = value[prop];
	}
	return retObj;
}
Rather succinct, I like it enough.

1 comment: