Have several native data structures for advanced usages.
Mainly use Array / Object to create custom or complicated data structures
There are 9 types
let buf = new ArrayBuffer(32)
buf.byteLength // declare a space with 32 byte (256 bits)
let arr = new Uint16Array(buf)
arr.length; // use this buffer to store Uint16 data, 256 ÷ 16 = 16 slots
When CPU access multiple bytes, there are two kinds of rules.
let buf = new ArrayBuffer(2)
let view8 = new Uint8Array(buf)
let view16 = new Uint16Array(buf)
view16[0] = 3085; // The binary representation is 0000110000001101 for integer 3085
view8[0]; // Most CPU use LSB, therefore, the binary representation for view8[0] is 00001101 (13 in decimal)
view8[1]; // The binary representation for view8[1] is 00001100 (12 in decimal)
view8[0].toString(16); // "d" in hex
view8[1].toString(16); // "c" in hex
// swap (as if endian!)
let tmp = view8[0];
view8[0] = view8[1];
view8[1] = tmp;
view16[0]; // The binary represnentation becomes 0000110100001100 (3340 in decimal)
Note: The same buffer could be controlled by many Views. If one view changes the buffer, the result will be reflected when using other views!
let a = new Uint32Array(3)
a[0] = 10;
a[1] = 20;
a[2] = 30;
let b = a.map(ele => ele * 2)
b.forEach(ele => console.log(ele)) // 20 40 60
b.push(100) // Uncaught TypeError: b.push is not a function
Since the number of bits are fixed, it could lead to an overflow!
let a = new Uint8Array(3)
a[0] = 10;
a[1] = 20;
a[2] = 30;
let b = a.map(ele => ele * ele)
b.forEach(ele => console.log(ele)) // 100 144 132
The biggest UInt for 1 byte (8 bits) could store is 255. The second and third slot (400 & 900) has an overflow.
TypedArray also have the method .from. It could receive an Iterable and return a whole new TypedArray/Array.
let a = new Uint8Array(3)
a[0] = 10;
a[1] = 20;
a[2] = 30;
let b = Uint16Array.from(a, ele => ele * ele)
console.log(b) // Uint16Array(3) [100, 400, 900]
Array sorts in alphabetical order, whereas TypedArray sorts in numeric order.
let a = [1,2,3,10,11]
let b = new UInt8Array(a)
a.sort() // [1, 10, 11, 2, 3]
b.sort() // [1, 2, 3, 10, 11]
When using objects, if keys are also objects, they will be overwritten. All keys will be stringified into "[object Object]".
let obj = {}
let x = { id: 1 }
let y = { id: 2 }
obj[x] = 'foo'
obj[y] = 'bar'
console.log(obj[x]) // bar
console.log(obj[y]) // bar
We could solve this issue by using Map. Anything could be used as a key without being stringified.
let m = new Map()
let x = { id: 1 }
let y = { id: 2 }
m.set(x, 'foo')
m.set(y, 'bar')
m.get(x) // foo
m.get(y) // bar
m.size // 2
m[x] // Can't use [] (bracket notation), could only use .set / .get
m.has(x) // true
m.delete(x) // can't use the keyword delete, must use .delete method in Map
m.has(x) // false
m.size // 1
m.clear() // clear all key/value pairs in Map
We could also pass a 2d array to construct a map. The first element of every subarray will be used as the key, while the second element will be used as the value. Elements after the second one will not be used.
let m = new Map([
['a', [1,2,3]],
['b', [4,5,6]]
])
m.get('a') // [1,2,3]
m.get('b') // [4,5,6]
We could use .values to extract the values of the Map, however, the return value will be an iterator. We could use ...(spread operator) or for-of to convert it into an array. (The same as .keys)
let m = new Map([
['a', 10]
['b', 20]
])
let vals = [...m.values()] // [10, 20]
Array.from(m.values()) // Could also use Array.from
for (let val of map.values()) {
console.log(val)
}
Like sets in math. Only hold unique values.
let s = new Set()
var x = { id: 1 },
y = { id: 2 }
s.add( x )
s.add( y )
s.add( x )
s.size // 2
s.delete( y )
s.size // 1
s.clear()
s.size
let s = new Set()
var x = { id: 1 },
y = { id: 2 },
z = { id: 1}
s.add(x)
s.add(y)
s.add(z)
s.size // 3 -> although x and z look identical in content, they point to different objects with their own memory space
let w = z
s.add(w)
s.size // 3 -> w & z points to the same space (same space in memory)
let s = new Set()
var x = { id: 1 },
y = { id: 2 },
z = { id: 3}
s.add(x).add(y).add(z)
[...s.keys()] // { id: 1 } { id: 2 } { id: 3 }
[...s.values()] // { id: 1 } { id: 2 } { id: 3 }
[...s.entries()]
// [{ id: 1 },{ id: 1 }] [{ id: 2 },{ id: 2 }] [{ id: 3 },{ id: 3 }]