一、Object
构造object对象有两种方式,一种是new 一种是对象字面量(类map)的方式。
访问属性可以用点号· 也可以用中括号
判断属性存不存在可以用typeof o.xxx
let o = new Object();
o.name = "doc";
let o1 = {
name: "doc"
}
console.log(o.name); // doc
console.log(o1["name"]);// doc11
console.log(typeof o1.age); // undefined
二、Array
创建:可以用new 或者 数组字面量,还可以使用Array.from(类数组)或者Array.of(一组参数)等静态方法来创建数组。
空位:数组初始化时,可以用一串逗号来创建空位。
索引:可以通过修改length属性,来删除或者添加元素。
检测:一般用instance of就行,但是有专门的判断Array方法,Array.isArray(xxxx);
迭代器:可以有keys(),values(),entries() 等方法。
复制和填充:复制可以用copywithin() 和fill()等方法。
转换方法:toString(),toValueOf(),toLocaleString()等。
栈方法:push()+pop()模拟栈。
队列方法:push()+shift()模拟队列。 unshift()和pop()可以模拟从队头添加元素,数组末尾取得数据。
排序方法:reverse()和sort();
操作:拼接:concat()如果不打平数组,可以用Sysmbol.isConcatSpreadable = false来阻止。
切片:slice(),从原始数组创建指定索引区间的数组。
删除、插入、替换都可以用splice(开始位置,要删除的元素数量,要插入的任意多个元素)
搜索和位置方法:indexOf,lastIndexOf,includes,find,findIndex等。
迭代:every()每一个都true才是true,some()有一个是true就是true。
filter 返回过滤出来为true的数组。 forEach()只是遍历,map就是转换数据之后构成的数组。
归并:reduce和reduceRight,这两方法都是迭代 数组所有项,并在此基础上构建一个最终返回值。
let c = new Array();
let c1 = new Array(3);
let c2 = new Array("red", "green");
let c3 = ["red", 'green'];
let b = Array.from(new Map().set(1, 2).set(3, 4));
let b2 = Array.from(new Set().add(1).add(2));
let b3 = Array.from({
*[Symbol.iterator]() {
yield 1;
yield 2;
}
})
let a1 = [1, 2, 3, 4];
let b4 = Array.from(a1, x => x ** 2);
let b5 = Array.of(1, 2, 3);
let e = [1, , , 5];
console.log(e.join('_'));
let ints = [1, 2, 3, 4, 5];
console.log(ints.copyWithin(3, 0, 2)); // [1, 2, 3, 1, 2]
console.log(ints.fill(3));// [3, 3, 3, 3, 3]
function compare(value1, value2) {
if (value1 < value2) {
return -1;
} else if (value1 > value2) {
return 1;
} else {
return 0;
}
}
// 直接传一个方法名,
// (method) Array<number>.sort(compareFn?: ((a: number, b: number) => number) | undefined): number[]
ints.sort(compare);
三、定型数组(typed array)
目的是为了提升向原生库传输数据的效率。比如Float32Array等。
3.1 ArrayBuffer
Float32Array实际是一种”视图“,可以允许js运行时访问一块名为ArrayBuffer的预分配内存。ArrayBuffer是所有定型数组及视图引用的基本单位。
ArrayBuffer() 是一个普通的js构造函数,可用于内存中分配特定数量的字节空间。
ArrayBuffer类似于C++中的malloc(),但是有明显区别:
malloc分配失败会返回null指针,而ArrayBuffer分配失败会抛错误。
malloc可以利用虚拟内存,最大分配尺寸只受寻址系统内存限制。ArrayBuffer分配的内存不能超过N.umber.MAX_SAFE_INTEGER字节。
malloc调用成功不会初始化实际的地址,声明ArrayBuffer则会将所有的二进制初始化为0;
malloc分配的堆内存除非调用free或程序退出,否则系统不能再使用,而通过生命ArrayBuffer分配的堆内存可以被垃圾回收,不用手动释放。
不能仅通过对ArrayBuffer的引用就能读写内容,要读取和写入ArrayBuffer就必须通过视图,视图有不同类型,但都是引用ArrayBuffer中存储的二进制数据。
3.2 DataView和定型数组
这两个就是视图,DataView主要用于文件I/O或者网络I/O, 定型数组:Int32Array等,特定的一种ElementType且遵循系统原生的字节序。
DataView在操作的使用ElementType来实现js的Number类型到缓冲内二进制格式的转换,且默认大端字节序。
ElementType:8种,Int8 Unit8 Int16 Uint16 Int32 Uint32 Float32 Float64
const buf = new ArrayBuffer(2);
const view = new DataView(buf);
view.setUint8(0,0x80);
view.setUint8(1,0x01);
console.log(view.getUint16(0)); // 32769
console.log(view.getUint16(0,true));// 384
DataView默认是大端字节序,也就是高位在前,低位在最后。如果启用小端字节序,这里就用true。
0x80:对应的二进制是1000 0000,(每个十六进制数字对应四位二进制【因为2的4次方就是16】,这里的8对应1000,8后的0对应0000,也就是10000000)。
Uint8 是一个数据类型,表示一个 8 位无符号整数(即一个字节)。view.setUint8(0, 0x80) 的作用是将一个 8 位无符号整数(一个字节)写入 DataView 对象的索引 0 处。
0x01: 对应的二进制是0000 0001
view.getUint16(0) 的计算按照大端字节序,也就是高位在左,低位在右,就是:1000 0000 0000 0001,算出来是2^15+2^1=32769;
view.getUint16(0,true) 的计算按照小端字节序,也就是低位在左,高位在右,就是反向拼接,0000 0001 1000 0000,计算出来就是2^8+2^7 = 384;
// 创建12字节的缓冲
const buf = new ArrayBuffer(12);
// 每一个元素需要4个字节,这里就只有3个元素
const ints = new Int32Array(buf);
console.log(ints.length); // 3
console.log(ints.byteLength);// 12
// 定型数组特殊的复制数据 set /subarray
const ints2 = new Int32Array(6);
ints2.set(Int32Array.of(1,2,3));
console.log(ints2); // 1 2 3 0 0 0
ints2.set(Int32Array.of(1,2,3),3);
console.log(ints2); // 1 2 3 1 2 3
const ints3 = ints2.subarray(1,2);
console.log(ints3);// 2
对于定型数组的上溢和下溢出,只会影响到相关位,不会影响到其他索引。
四、Map/WeakMap/Set/WeakSet
// 直接使用new
const m1 = new Map();
m1.set("sss","1");
// 嵌套数组初始化映射
const m2 = new Map([
["sss","1"]
]);
// 使用自定义迭代器
const m3 = new Map({
[Symbol.iterator]:function*(){
yield ["sss","1"];
}
});
for(let pair of m1.entries()){
console.log(pair);// ['sss', '1']
}
for(let pair of m3[Symbol.iterator]()){
console.log(pair); // ['sss', '1']
}
for(let key of m1.keys()){
console.log(key); // sss
}
for(let value of m1.values()){
console.log(value);// 1
}
m1.forEach((val,key)=>console.log(`${val}+${key}`)) // 1+sss
Set也有类似的方法,同上
WeakMap、WeakSet中前者对key必须是Object或者继承Object类型,后者是值必须是Object或者继承Object类型。
4.1.1选择Object还是Map主要看:
同样内存,map可以比object多存50%的键值对。
插入和删除Map更好,查询Object更好一些。
WeakMap和WeakSet不可以迭代。
从es6开始Map和Set都是有序的了。