JavaScript has long included typed arrays to efficiently store numeric arrays. Each kind of typed array had its own constructor. Typed arrays inherited from element-type-specific prototypes: Int8Array.prototype
, Float64Array.prototype
, Uint32Array.prototype
, and so on. Each of these prototypes contained useful methods (set
, subarray
) and properties (buffer
, byteOffset
, length
, byteLength
) and inherited from Object.prototype
.
This system is a reasonable way to expose typed arrays. Yet as typed arrays have grown, it’s grown unwieldy. When a new typed array method or property is added, distinct copies must be added to Int8Array.prototype
, Float64Array.prototype
, Uint32Array.prototype
, &c. Likewise for “static” functions like Int8Array.from
and Float64Array.from
. These distinct copies cost memory: a small amount, but across many tabs, windows, and frames it can add up.
A better system
ES6 changes typed arrays to fix these issues. The typed array functions and properties now work on any typed array.
var f32 = new Float32Array(8); // all zeroes var u8 = new Uint8Array([0, 1, 2, 3, 4, 5, 6, 7]); Uint8Array.prototype.set.call(f32, u8); // f32 contains u8's values
ES6 thus only needs one centrally-stored copy of each function. All functions move to a single object, denoted %TypedArray%.prototype
. The typed array prototypes then inherit from %TypedArray%.prototype
to expose them.
assertEq(Object.getPrototypeOf(Uint8Array.prototype), Object.getPrototypeOf(Float64Array.prototype)); assertEq(Object.getPrototypeOf(Object.getPrototypeOf(Int32Array.prototype)), Object.prototype); assertEq(Int16Array.prototype.subarray, Float32Array.prototype.subarray);
ES6 also changes the typed array constructors to inherit from the %TypedArray%
constructor, on which functions like Float64Array.from
and Int32Array.of
live. (Neither function yet in Firefox, but soon!)
assertEq(Object.getPrototypeOf(Uint8Array), Object.getPrototypeOf(Float64Array)); assertEq(Object.getPrototypeOf(Object.getPrototypeOf(Int32Array)), Function.prototype);
I implemented these changes a few days ago in Firefox. Grab a nightly build and test things out with a new profile.
Conclusion
In practice this won’t affect most typed array code. Unless you depend on the exact [[Prototype]]
sequence or expect typed array methods to only work on corresponding typed arrays (and thus you’re deliberately extracting them to call in isolation), you probably won’t notice a thing. But it’s always good to know about language changes. And if you choose to polyfill an ES6 typed array function, you’ll need to understand %TypedArray%
to do it correctly.
Thanks for the heads up about this!
Comment by azakai — 26.09.14 @ 15:10