不常见的数据类型
这里是一些不常见的数据类型
Symbol
可以创建一个唯一的值
new Symbol();
// Uncaught TypeError: Symbol is not a constructor
const symbol1 = Symbol("lucas");
const symbol2 = Symbol("lucas");
symbol1 !== symbol2; // true
js 运行过程会设置一个全局 Symbol 注册表,可以通过Symbol.for(key)
检索指定 key 的 Symbol 值
使用场景
- 定义常量(枚举)
- 对象私有属性。需要注意的是:遍历对象的时候,该属性不会出现在
for...in
、for...of
循环中,也不会被Object.keys()、Object.getOwnPropertyNames()、JSON.stringify()
返回,可以用Object.getOwnPropertySymbols()
获取 - 实现一个可遍历的对象
const obj = {
from: 0,
to: 10,
[Symbol.iterator]: function () {
return {
current: this.from,
last: this.to,
next() {
if (this.current <= this.last) {
return { done: false, value: this.current++ };
} else {
return { done: true };
}
},
};
},
};
for (let num of obj) {
console.log(num);
}
- 其他内置 Symbol
Symbol.match
Symbol.toPrimitive
BigInt
可以用任意精度表示整数,并且可以正确执行整数运算而不会溢出。同为 BigInt 类型的变量才能做运算,并且 BigInt 永远不会等于 Number
new BigInt(5);
// Uncaught TypeError: BigInt is not a constructor
5n === BigInt(5);
const previousMaxSafe = BigInt(Number.MAX_SAFE_INTEGER);
// 9007199254740991n
const maxPlusOne = previousMaxSafe + 1n;
// 9007199254740992n
BigInt(1.5);
// RangeError
BigInt("1.5");
// SyntaxError
// 注意这里的类型转换
typeof 1n === "bigint"; // true
typeof BigInt("1") === "bigint"; // true
但要注意运算符有使用局限,比如不能用单目运算符、不能使用无符号右移等,详见 BigInt-MDN
Map
Map
跟普通对象的区别是不限键类型,并且是有序的
new Map()
map.set(key, value)
map.get(key)
map.has(key)
map.delete(key)
map.clear()
map.size
const map = new Map();
map.set("1", "lucas");
map.set(1, "gogogo");
console.log(map.get(1)); // 'gogogo'
console.log(map.get("1")); // 'lucas'
console.log(map.size); // 2
const obj = { name: "lucas" };
map.set(obj, "gogogo");
将对象转换成 Map 对象
const prices = new Map([
["banana", 1],
["orange", 2],
["meat", 10],
]);
使用 Object.fromEntries
将 Map 对象转换成一个普通对象
const prices = Object.fromEntries([
["banana", 1],
["orange", 2],
["meat", 10],
]);
// prices: { banana: 1, orange: 2, meat: 10 }
遍历 Map 对象可以用 map.keys()/map.values()/map.entrie()
Set
Set
跟普通数组的区别主要在于唯一,并且没有下标的概念
new Set(iterable)
set.add(value)
。返回 Set 对象本身set.delete(value)
。删除值,如果 value 在这个方法调用的时候存在则返回 true ,否则返回 falseset.has(value)
set.clear()
set.size
let set = new Set();
let a = { name: "a" };
let b = { name: "b" };
let c = { name: "c" };
set.add(a);
set.add(b);
set.add(c);
set.add(a);
set.add(b);
alert(set.size); // 3
可以使用 for..of
或 forEach
来遍历 Set。除此之外,也可以用 set.keys()/set.values()/set.entrie()
实现遍历
let set = new Set(["oranges", "apples", "bananas"]);
set.forEach((value, valueAgain, set) => {
// 这里的三个参数,前两者是一样的。注意下标是数组特有的东西
console.log(value, valueAgain);
});
WeakMap
WeakMap
只能接受对象作为键,并保持了对键名所引用的对象的弱引用,在没有其他引用和该键引用同一对象,这个对象将会被垃圾回收(相应的 key 则变成无效的)
WeakSet
WeakSet
只能接受对象作为值,并且储存的对象都是被弱引用的,如果没有其他的变量或属性引用这个对象值,则这个对象将会被垃圾回收掉(不考虑该对象还存在于 WeakSet 中)