ArrayBuffer
The ArrayBuffer object, along with TypedArray and DataView views, provides an interface for JavaScript to manipulate binary data.
Binary Arrays Consist of Three Types of Objects
- ArrayBuffer Object: Represents a segment of binary data in memory, which can be manipulated through “views.” These views implement an array interface, allowing memory to be operated on using array methods.
- TypedArray Views: Includes 9 types of views, such as
Uint8Array(unsigned 8-bit integer),Int16Array(16-bit integer),Float32Array(32-bit floating point), and others. - DataView Views: Allows custom composite formats, e.g., the first byte as
Uint8(unsigned 8-bit integer), the second and third bytes asInt16(16-bit integer), and from the fourth byte onward asFloat32(32-bit floating point). It also supports custom byte order.
In summary, ArrayBuffer represents raw binary data, TypedArray views handle simple binary data types, and DataView views manage complex binary data types.
ArrayBuffer Object
const buf = new ArrayBuffer(32);
const dataView = new DataView(buf);
dataView.getUint8(0); // 0
ArrayBuffer.isView(buf); // false
const newBuffer = buf.slice(0, 3);
const x1 = new Int32Array(buf);
x1[0] = 1;
const x2 = new Uint8Array(buf);
x2[0] = 2;
x1[0]; // 2TypedArray Views
Int8Array: 8-bit signed integer, 1 byte.Uint8Array: 8-bit unsigned integer, 1 byte.Uint8ClampedArray: 8-bit unsigned integer, 1 byte, with different overflow handling.Int16Array: 16-bit signed integer, 2 bytes.Uint16Array: 16-bit unsigned integer, 2 bytes.Int32Array: 32-bit signed integer, 4 bytes.Uint32Array: 32-bit unsigned integer, 4 bytes.Float32Array: 32-bit floating point, 4 bytes.Float64Array: 64-bit floating point, 8 bytes.
// Create an 8-byte ArrayBuffer
const b = new ArrayBuffer(8);
// Create an Int32 view pointing to b, starting at byte 0, until the buffer's end
const v1 = new Int32Array(b);
// Create a Uint8 view pointing to b, starting at byte 2, until the buffer's end
const v2 = new Uint8Array(b, 2);
// Create an Int16 view pointing to b, starting at byte 2, with a length of 2
const v3 = new Int16Array(b, 2, 2);
// Composite view
const buffer = new ArrayBuffer(24);
const idView = new Uint32Array(buffer, 0, 1);
const usernameView = new Uint8Array(buffer, 4, 16);
const amountDueView = new Float32Array(buffer, 20, 1);DataView Views
The DataView view is a constructor that takes an ArrayBuffer object as an argument to generate a view.
DataView.prototype.buffer: Returns the associatedArrayBufferobject.DataView.prototype.byteLength: Returns the number of bytes occupied by the view.DataView.prototype.byteOffset: Returns the starting byte offset of the view within theArrayBuffer.
DataView provides 8 methods to read memory:
getInt8: Reads 1 byte, returns an 8-bit integer.getUint8: Reads 1 byte, returns an unsigned 8-bit integer.getInt16: Reads 2 bytes, returns a 16-bit integer.getUint16: Reads 2 bytes, returns an unsigned 16-bit integer.getInt32: Reads 4 bytes, returns a 32-bit integer.getUint32: Reads 4 bytes, returns an unsigned 32-bit integer.getFloat32: Reads 4 bytes, returns a 32-bit floating point number.getFloat64: Reads 8 bytes, returns a 64-bit floating point number.
const buffer = new ArrayBuffer(24);
const dv = new DataView(buffer);
// Read an 8-bit unsigned integer from the first byte
const v1 = dv.getUint8(0);
// Read a 16-bit unsigned integer from the second byte
const v2 = dv.getUint16(1);
// Read a 16-bit unsigned integer from the fourth byte
const v3 = dv.getUint16(3);Binary Array Applications
AJAX
let xhr = new XMLHttpRequest();
xhr.open('GET', someUrl);
xhr.responseType = 'arraybuffer';
xhr.onload = function () {
let arrayBuffer = xhr.response;
// ...
};
xhr.send();Canvas
const canvas = document.getElementById('myCanvas');
const ctx = canvas.getContext('2d');
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
const uint8ClampedArray = imageData.data;WebSocket
let socket = new WebSocket('ws://127.0.0.1:8081');
socket.binaryType = 'arraybuffer';
// Wait until socket is open
socket.addEventListener('open', function (event) {
// Send binary data
const typedArray = new Uint8Array(4);
socket.send(typedArray.buffer);
});
// Receive binary data
socket.addEventListener('message', function (event) {
const arrayBuffer = event.data;
// ...
});Fetch API
fetch(url)
.then(function (response) {
return response.arrayBuffer();
})
.then(function (arrayBuffer) {
// ...
});File API
const fileInput = document.getElementById('fileInput');
const file = fileInput.files[0];
const reader = new FileReader();
reader.readAsArrayBuffer(file);
reader.onload = function () {
const arrayBuffer = reader.result;
// ...
};Decorator
Decorators are a class-related syntax for annotating or modifying classes and class methods. They are currently in the proposal stage.
@frozen
class Foo {
@configurable(false)
@enumerable(true)
method() {}
@throttle(500)
expensiveMethod() {}
}
class Person {
@readonly
name() {
return `${this.first} ${this.last}`;
}
}
@Component({
tag: 'my-component',
styleUrl: 'my-component.scss',
})
@testable
class Person {
@nonenumerable
@Prop()
first: string;
@Prop()
last: string;
@State()
isVisible: boolean = true;
get kidCount() {
return this.children.length;
}
}
import { traits } from 'traits-decorator';
@traits(TFoo, TBar)
class MyClass {}Functional Programming
In JavaScript, you can adopt either object-oriented or functional programming paradigms. Some even claim JavaScript was the first widely adopted functional programming language.
Currying
Currying transforms a multi-parameter function into a series of single-parameter (unary) functions.
function add(a) {
return function (b) {
return a + b;
};
}
// Or using arrow functions
const add = x => y => x + y;
const f = add(1);
f(1); // 2Function Composition
Function composition combines multiple functions into a single function.
const compose = f => g => x => f(g(x));
const f = compose(x => x * 4)(x => x + 3);
f(2); // 20Parameter Flipping
Parameter flipping reverses the order of a function’s first two parameters.
var divide = (a, b) => a / b;
var flip = f.flip(divide);
flip(10, 5); // 0.5
flip(1, 10); // 10
var three = (a, b, c) => [a, b, c];
var flip = f.flip(three);
flip(1, 2, 3); // [2, 1, 3]Execution Boundary
The until operation executes a function until a condition is met.
let condition = x => x > 100;
let inc = x => x + 1;
let until = f.until(condition, inc);
until(0); // 101
condition = x => x === 5;
until = f.until(condition, inc);
until(3); // 5List Operations
List operations include:
head: Retrieves the first non-empty member of a list.last: Retrieves the last non-empty member of a finite list.tail: Retrieves all non-empty members except the head.init: Retrieves all non-empty members except the last.
f.head(5, 27, 3, 1); // 5
f.last(5, 27, 3, 1); // 1
f.tail(5, 27, 3, 1); // [27, 3, 1]
f.init(5, 27, 3, 1); // [5, 27, 3]
// Implementation of these methods
let f = {};
f.head = (...xs) => xs[0];
f.last = (...xs) => xs.slice(-1);
f.tail = (...xs) => Array.prototype.slice.call(xs, 1);
f.init = (...xs) => xs.slice(0, -1);Concatenation Operations
Concatenation operations include concat and concatMap. The former merges multiple arrays into one, while the latter processes parameters before merging the results into an array.
f.concat([5], [27], [3]); // [5, 27, 3]
f.concatMap(x => 'hi ' + x, 1, [[2]], 3); // ['hi 1', 'hi 2', 'hi 3']
// Implementation of these methods
let f = {};
f.concat = (...xs) => xs.reduce((a, b) => a.concat(b));
f.concatMap = (f, ...xs) => f.concat(xs.map(f));Pairing Operations
Pairing operations include zip and zipWith. The zip operation pairs members of two lists into a new list of pairs.
let a = [0, 1, 2];
let b = [3, 4, 5];
let c = [6, 7, 8];
f.zip(a, b); // [[0, 3], [1, 4], [2, 5]]
f.zipWith((a, b) => a + b, a, b, c); // [9, 12, 15]
// Implementation of these methods
let f = {};
f.zip = (...xs) => {
let r = [];
let nple = [];
let length = Math.min.apply(null, xs.map(x => x.length));
for (var i = 0; i < length; i++) {
xs.forEach(x => nple.push(x[i]));
r.push(nple);
nple = [];
}
return r;
};
f.zipWith = (op, ...xs) => f.zip.apply(null, xs).map(x => x.reduce(op));



