Copying an array the weird way

JavaScript performance comparison

Test case created by Dan Tao

Info

We all know you can copy an array multiple ways. There's Array.prototype.slice; there's the old-fashioned way where you create a new array and push the results onto it. A little optimization (for some browsers) is to construct the array with the appropriate length and then assign its elements rather than push.

What if we "copy" the original using a totally weird, different approach?

This is not a good idea for real code. It's just a fun exercise.

Behold this function:

function copyArray(arr) {
  var copy = function() {};
  copy.prototype = arr;
  return new copy();
}

var arr1 = [1, 2, 3],
    arr2 = copyArray(arr1);

arr2.length;    // => 3
arr2[0];        // => 1
arr2.join(','); // => '1,2,3'

arr2.push(4);    // arr1 == [1, 2, 3], arr2 == [1, 2, 3, 4]
arr2[0] = 'foo'; // arr1 == [1, 2, 3], arr2 == ['foo', 2, 3, 4]

Pretty interesting, huh?

Of course, then there's this:

arr1[1] = 'bar'; // arr2 == ['foo', 'bar', 3, 4]

And also this:

JSON.stringify(arr2); // => '{}'

So... yeah. Like I said, don't use this for real. But still! Interesting!

Preparation code

<script>
function copySlice(arr) {
  return arr.slice(0);
}

function copyPush(arr) {
  var copy = [];
  for (var i = 0, len = arr.length; i < len; ++i) {
    copy.push(arr[i]);
  }
  return copy;
}

function copyAssign(arr) {
  var copy = Array(arr.length);
  for (var i = 0, len = arr.length; i < len; ++i) {
    copy[i] = arr[i];
  }
  return copy;
}

function copyProto(arr) {
  var copy = function() {};
  copy.prototype = arr;
  return new copy();
}

// Create an array w/ 500 elements to test
var array = [];
while (array.length < 500) {
  array.push(array.length);
}
</script>

Test runner

Warning! For accurate results, please disable Firebug before running the tests. (Why?)

Java applet disabled.

Testing in unknown unknown
Test Ops/sec
slice
copySlice(array);
pending…
push
copyPush(array);
pending…
assign
copyAssign(array);
pending…
prototype
copyProto(array);
pending…

You can edit these tests or add even more tests to this page by appending /edit to the URL.

Compare results of other browsers

0 comments

Add a comment