Thursday, April 13, 2017

Javascript typed arrays - slice vs subarray



What

Both of these TypedArrays' methods appear to do the same thing, except for a cool difference. Let's start with examples..

const a = new Uint8Array([1, 2, 3, 4]);

const b = a.slice(1, 3); // b becomes Uint8Array [ 2, 3 ]
const c = a.subarray(1, 3); // c becomes Uint8Array [ 2, 3 ]

Now let's see what happens when we change the values of these new arrays

b[0] = 5; // b is now Uint8Array [ 5, 3 ]
console.log(a); // Uint8Array [ 1, 2, 3, 4 ]

c[0] = 5; // c is now Uint8Array [ 5, 3 ]
console.log(a); // Uint8Array [ 1, 5, 3, 4 ]

See what happened at line 5? when we changed c, a has changed too, where on the other hand, b doesn't have the same effect, that's the difference.


Why

As you know, subarray exists only for typed arrays, that's the key to understand what's going on.

TypedArrays in javascript are represented in the memory as a single slab of bytes with the size reflecting the number of array items (if every item is one byte and the array has 3 items, then the memory taken is 3 bytes). Let's compare what slice does with what subarray does..

  • slice: Allocate a new space in memory and copy the items from the original array between the start and end indices provided in the arguments into these new memory locations, return the new array.
  • subarray: make a new empty typed array object, which points to a part of the original array between the start and end indices provided in the arguments.

So basically subarray lets a and c see and modify the same memory locations, it provides a smaller "view" (window) over the original array.

That makes subarray very fast compared to slice, because no copying is involved.


When

you can take advantage of this when you have a huge array that you want to convert a range of it into another type. One such situation that comes to mind is when the canvas demands a Uint8ClampedArray to draw its pixels.

const d = new Uint8ClampedArray(c);

the constructor sees c as a Uint8Array, because it really is an independent array which happens to look at the same memory location as a.

This gives you a new array d with the contents of a part of a without having to create an intermediate copy of the range that we want from a.


I hope I have managed to clear up the difference. feel free to ask questions, point out flaws and speak your mind in the comments.

1 comment: