js基石之数据类型一:类型分类&区别
js基石之数据类型二:类型判断
js基石之数据类型三:类型转换
js基石之Number:本质
js基石之Number:应用(数字运算,数字&字符串转换,不同进制表示&相互转换)
js基石之字符: ASCII,GBK,Unicode,utf-32,utf-16,utf-8,encodeuri,encodeuricomponent,base64
js基石之Symbol值
先有问题再有答案
Symbol是什么
Symbol和其他数据类型有什么关系?
Symbol有什么特性
有哪些应用场景
你都掌握了哪些有用的Symbol值?
Symbol是什么
symbol是一种基本数据类型, 通过Symbol函数生成symbol值,symbol值都是唯一的。一个 symbol 值能作为对象属性的标识符;这是该数据类型仅有的目的
一个原始值
javascript
const s = Symbol('a')
typeof s // 'symbol'
Symbol函数
Symbol作为函数的唯一作用就是生成symbol值。
Symbol对象
- 对象属性:Symbol.iterator,Symbol.toPrimitive,Symbol.toStringTag...
- 原型方法:Symbol.prototype原型定义了toString,valueOf方法 同时Symbol原型链上也有Function.prototype&Object.prototype。
- 静态方法:Symbol.for,Symbol.keyFor
Symbol&其他类型
Number: 不能相互转换
javascript
let sym = Symbol('1');
let num = sym + 1; // Uncaught TypeError: Cannot convert a Symbol value to a number
Number(sym) // Uncaught TypeError: Cannot convert a Symbol value to a number
parseInt(sym) // Uncaught TypeError: Cannot convert a Symbol value to a number
String:不能隐式转换
ini
let sym = Symbol('test');
let str = sym + 'hello'; // Cannot convert a Symbol value to a string
可以显式转换
ini
let sym = Symbol('test');
let str1 = sym.toString(); // 使用 Symbol.prototype.toString 方法进行转换
// 返回:"Symbol(test)"
let str2 = String(sym); // 使用 String 函数进行转换
// 返回:"Symbol(test)"
Boolean
所有的 Symbol 类型的值在转换为布尔值时都是 true,无论它们的描述是什么
ini
let sym1 = Symbol('test');
let bool1 = !!sym1; // 返回:true
let sym2 = Symbol();
let bool2 = !!sym2; // 返回:true
let bool = Boolean(sym2); // 返回:true
包装类
Symbol函数不能通过new调用,没有对应的包装类 es2015之后新增的基本数据类型(BigInt)都不能通过new调用,这是JavaScript 语言的设计决定。
虽然引擎提供了自动装箱和拆箱功能,但是Symbol&BigInt两种类型 不适合当做对象使用。
Symbol的特性
1:symbol没有字面量形式 只能通过Symbol函数生成。
ini
let sym1 = Symbol('test');
2:symbol表示唯一值
每个 Symbol 值都是唯一的,即使你创建了两个具有相同描述的 Symbol 值,它们也是不相等的。这使得 Symbol 值成为了创建对象的唯一属性键的理想选择,可以避免属性名的冲突。
ini
let sym1 = Symbol('test');
let sym2 = Symbol('test');
sym1 === sym2 // false
3:不可枚举
Symbol 值作为对象的属性键时,这个属性不会出现在常规的遍历操作中(如 for...in 循环、Object.keys()、JSON.stringify() 等),只能通过 Object.getOwnPropertySymbols() 或 Reflect.ownKeys() 来获取。
ini
let sym = Symbol('test');
let obj = { [sym]: 'value', prop: 'value' };
console.log(Object.keys(obj)); // 输出:['prop'] console.log(Object.getOwnPropertySymbols(obj)); // 输出:[Symbol(test)]
应用场景
创建唯一的属性键:
由于每个 Symbol 都是唯一的,所以可以用它来创建唯一的属性键,避免属性名的冲突。
ini
let id = Symbol('id');
let user = {
[id]: 1,
name: 'John',
age: 30
};
内置的Symbol值(常用的)
Symbol.iterator:迭代器
javascript
let iterable = {
[Symbol.iterator]() {
let i = 0;
return {
next() {
if (i < 5) {
return { value: i++, done: false };
} else {
return { value: undefined, done: true };
}
}
};
}
};
for (let value of iterable) {
console.log(value); // 输出:0, 1, 2, 3, 4
}
Symbol.toPrimitive:类型转换
csharp
const obj = {
value: 1,
[Symbol.toPrimitive](){
return 10
},
};
obj + 1 // 11
obj + '1' // '101'
'1' + obj // 110
Symbol.toStringTag:类型判断
javascript
Number.prototype[Symbol.toStringTag] = 'String';
let a = 12;
Object.prototype.toString.call(a) // '[object String]'成功的将数字改变为字符串
补充
symbol具有唯一性。还有哪些方式可以表示唯一性
?
- 时间戳
ini
let timestamp = Date.now();
- 使用 Math.random():
Math.random() 函数返回一个介于 0(包含)和 1(不包含)之间的随机数,所以你可以用它来生成一个几乎唯一的值。但是,Math.random() 函数的结果是不可预测的,所以它不能保证生成的值一定是唯一的。
vbscript
Math.random().toString(36).substring(2)
- uuid
javascript
npm install uuid
import { v4 as uuidv4 } from 'uuid';
uuidv4(); // ⇨ '9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d'