JS高阶(二)Symbol

2022-08-05 19:31:03 浏览数 (1)

使用场景

ES6 引入了一种新的原始数据类型 Symbol ,表示独一无二的值,最大的用法是用来定义对象的唯一属性名。

ES6 数据类型除了 Number 、 String 、 Boolean 、 Object、 null 和 undefined ,还新增了 Symbol 。

基本用法

Symbol 函数栈不能用 new 命令,因为 Symbol 是原始数据类型,不是对象。可以接受一个字符串作为参数,为新创建的 Symbol 提供描述,用来显示在控制台或者作为字符串的时候使用,便于区分。

代码语言:javascript复制
let sy = Symbol("KK");
console.log(sy); // Symbol(KK) 
typeof(sy); // "symbol" 
// 相同参数 Symbol() 返回的值不相等 
let sy1 = Symbol("kk");
sy === sy1; // false
定义方式 Symbol()
代码语言:javascript复制
let hd = Symbol();
let demo = Symbol();

console.log(typeof hd); //Symbol
demo === hd; //false

Symbol 数据类型的数据无法压入属性。可以通过 Symbol 添加描述来进行标记 Symbol 数据类型的数据对象;

代码语言:javascript复制
let id = Symbol('学生id');
console.log(id); //Symbol(学生id)
cnosole.log(id.toString()); //Symbol(学生id)
console.log(id.description); //学生id
另一种定义方式 Symbol.for()
代码语言:javascript复制
/* 
 * 理解:声明多次仅有一个symbol数据
 * 以一个symbol数据的description为父类
 * 相同的symbol对象全部归为其子类
*/
let a = Symbol.for('test demo');
let b = Symbol.for('test demo');

console.log(a); //Symbol(test demo)
a === b; //true 可以反复使用symbol

//获取symbol.for对象的description
console.log(Symbol.keyFor('a')); //test demo
使用symbol解决字符串耦合问题
代码语言:javascript复制
//出现的问题:在多个数据头重复的情况下不能很好的操作数据值
// => 字符串耦合
let user1 = '李四';
let user2 = '李四';
let grade = {
	[user1]:{js:100, css:89},
	[user2]:{js:98, css:55}
}
  • 使用symbol解决字符串耦合:
代码语言:javascript复制
//使用symbol来控制key的唯一性(伪键值对)
let user1 = {
	name: "李四",
	key: Symbol()
};
let user2 = {
	name: "李四",
	key: Symbol()
};

//通过唯一的symbol来控制对象属性
let grade = {
	//使用中括号防止解析为string
	[user1.key]: {js: 100, css: 89},
	[user2.key]: {js: 76, css: 55}
}
console.log(grade[user1.key]);
Symbol在缓存容器中的使用

前后端分离:前台使用模块化组件化形态,独立模块间共享数据会被存在容器池(缓存容器)中,当使用字符串缓存时可能存在重名/重复的现象;

普通创建缓存容器池方法:

代码语言:javascript复制
//创建缓存对象类
class cache = {
	//创建对象
	static data = {};
	//set设置值方法
	static set(name, value){
		return (this.data[name] = value);
	}
	//get取出值方法
	static get(name){
		return this.data[name];
	}
}
//缓存数据
cache.set("demo-name", "test-value");
//读取数据
console.log(cache.get("demo-name"));

let user = {
	name: "apple",
	desc: "用户资料"
};
let cart = {
	name: "apple",
	desc: "购物车"
};

//以下会造成数据复写和覆盖
cache.set('apple', user);
cache.set('apple', cart);

//从缓存池中抽取数据
console.log(cache.get("apple")); //因此需要单独控制name值

使用Symbol在缓存容器池中解决耦合问题:

  • 为每个对象压入一个 symbol 数据类型的 key 指向;
  • 理解方式:map<k,v>键值对来唯一化每个被标记的数据;
代码语言:javascript复制
let user = {
	name: "apple",
	desc: "用户资料",
	key: Symbol("会员资料")
};
let cart = {
	name: "apple",
	desc: "购物车",
	key: Symbol("购物车数据")
};

//压入每个对象独一无二的key值
cache.set(user.key, user);
cache.set(cart.key, cart);

//取出数据
console.log(cache.get(user.key));
console.log(cache.get(cart.key));
扩展特性
代码语言:javascript复制
let sy = symbol('这是一个symbol对象');
let test-obj = {
	name: 'demo',
	[symbol]: 'www.baidu.com' //伪私有属性
}
for (const key in test-obj) {
	console.log(key); //symbol无法读取
}
for (const key of Object.keys(test-obj)) {
	cnosole.log(key); //symbol无法读取
}

// 如何读取symbol属性值?
for (const key of Object.getOwnProPpertySymbols(test-obj)) {
	console.log(key); //只能遍历到symbol对象
}

//方法二:获取包括了symbol属性的方法
for (const key of Reflect.ownKeys(test-obj)) {
	console.log(key); //遍历到所有属性
}
  • 注意:
    • 仅获取到对象的 Symbol 属性遍历法:
      • Object.getOwnPropertySymbols(object)
    • 获取到对象内包括 Symbol 的所有属性的方法:
      • Reflect.ownKeys(object)
对象属性保护

借助上述扩展特性可以将对象属性私有化:

代码语言:javascript复制
let site = Symbol('这是一个symbol对象');
class User {
	constructor(name){
		this.name = name;
		this[site] = 'demo-name';
	}
	getName(){
		return `${this[site]} ${this.name}`;
	}
}

let edu = new User('张三');
console.log(edu.getName()); //demo-name 张三

for(const key in edu){
	console.log(key); //得到name属性
}

0 人点赞