美文网首页前端开发那些事儿
ES6新特性Symbol,Set,Map

ES6新特性Symbol,Set,Map

作者: 大吉的罐头 | 来源:发表于2021-03-06 13:18 被阅读0次

新数据类型 Symbol

声明方式
  • Symbol 不是对象,可以理解成不能重复的独立字符串,括号内对象会转化为字符串
  • Symbol for 在全局中定义查找,创建多个其实查找是同一个
  • Symbol.keyFor 返回已经登记的Symbol类型的key
const obj={
    name:'daji',
    toString(){
        return this.name
    }
}
let n=Symbol(obj)
console.log(n); //Symbol(daji)

let c=Symbol([1,2,3])
console.log(c);  //Symbol(1,2,3)

let s1=Symbol('foo')
let s2=Symbol('foo')
console.log(s1===s2); //false

let a1=Symbol.for('foo')
let a2=Symbol.for('foo')
console.log(a1===a2);  //true

const x1=Symbol('foo')
console.log(Symbol.keyFor(x1)); //undefined
const x2=Symbol.for('foo')
console.log(Symbol.keyFor(x2)); //foo
应用场景
  • 对象内如果有重复key值会覆盖的解决方式
const stu1=Symbol('李四')
const stu2=Symbol('李四')
const grade={
    [stu1]:{address:'yyy',tel:'111'},
    [stu2]:{address:'yyy',tel:'111'}
}
console.log(grade); //{Symbol('李四'):{...},Symbol('李四'):{...}} 不会覆盖,显示两个
console.log(grade[stu1]);
console.log(grade[stu2]);
  • 一定程度上保护构造函数的属性
let sym=Symbol('hello')
class User{
    constructor(name){
        this.name=name
        this[sym]='hello.com'
    }
    getName(){
        return this.name+this[sym]
    }
}
let user=new User('daji')
console.log(user.getName()); //dajihello.com

for(let key in user){
    console.log(key);  //name 无法读到Symbol('hello')属性
}
for(let key of Object.keys(user)){
    console.log(key);  //name 无法读到Symbol('hello')属性
}
for(let key of Object.getOwnPropertyNames(user)){
    console.log(key);  //name 无法读到Symbol('hello')属性
}
for(let key of Object.getOwnPropertySymbols(user)){
    console.log(key);  //Symbol(hello)   只能读到symbol属性,读不到name
}
for(let key of Reflect.ownKeys(user)){
    console.log(key);   //name Symbol(hello)  都能读到
}
  • 消除魔术字符串(重复出现的字符串)
const shpeType={
    triangle:Symbol(),  //triangle:'triangle' vlaue值不重要用symbol替代
    circle:Symbol()     //circle:'circle' 
}
function getArea(shape){
    let area = 0
    switch(shape){
        case shpeType.triangle:  //避免case 'triangle' 重复出现此字符串
            area=1
            break
        case shpeType.circle:
            area=2
            break
    }
    return area
}
console.log(getArea(shpeType.triangle));  //返回1  避免getArea('triangle') 重复出现此字符串

新数据结构 Set

常用方法
//唯一的 重复的2只会保留1个2
let s=new Set([1,2,3,2])
s.add('es').add('hi')  //链式添加
s.delete(2)  //删除
s.clear()   //清空
console.log(s.has('hi')); //是否包含
console.log(s); 
console.log(s.size);  //size相当于length
遍历方法
let s1=new Set([1,2,3,2])  //只保留了1个2
console.log(s1);
s1.forEach(item=>{
    console.log(item);  // 1 2 3
})
for(let item of s1){
    console.log(item);   //1 2 3
}
for(let item of s1.keys()){
    console.log(item);   //1 2 3
}
for(let item of s1.values()){
    console.log(item);   //1 2 3
}
for(let item of s1.entries()){
    console.log(item);   //[1,1] [2,2] [3,3] key和value
}
应用场景
  • 数组去重
let arr = [1,2,3,4,2,3]
let s= new Set(arr)
console.log(s);  //set(4){1,2,3,4}
  • 合并去重
let arr1=[1,2,3,4]
let arr2=[2,3,4,5,6]
let s1=new Set([...arr1,...arr2])  //扩展运算符打散 set(6){1,2,3,4,5,6}
console.log(s1);      //set(4) [1,2,3,4,5,6]
console.log([...s1]); //变成数组形式 [1,2,3,4,5,6]
console.log(Array.from(s1));  //变成数组形式 [1,2,3,4,5,6]
  • 交集
let s3=new Set(arr1);
let s4=new Set(arr2);
let result=new Set(arr1.filter(item=>s4.has(item)));
console.log(result); //set(4) {2,3,4}
  • 差集 (两数组合并后除去交集)
let result1=new Set(arr1.filter(item=>!s4.has(item)));
let result2=new Set(arr2.filter(item=>!s3.has(item)));
console.log(result1); //set{1}
console.log(result2); //set{5,6}
console.log([...result1,...result2]); //[1,5,6]
  • WeakSet (只能存储对象)
let ws =new WeakSet()
const obj1={a:1}
const obj2={b:2}
ws.add(obj1)
ws.add(obj2)
ws.delete(obj1)
console.log(ws);
console.log(ws.has(obj2));
//WeakSet 不能遍历
ws.forEach(item=>{console.log(item);})
//WeakSet 是弱引用,不进入垃圾回收机制(值被引用一次+1)不存在回收问题,适合临时存放一些对象

新数据结构 Map

常用方法
//Map键值对的方式,但key可以为对象
let m=new Map()
let obj={
    name:'daji'
}
m.set(obj,'es')  //设置  对象做为key,value值对应es
console.log(m); 
console.log(m.get(obj)); //获取 es
m.delete(obj)
console.log(m); //删除  空
console.log(m.has(obj)); //false

//这样设置key和value也行
let map=new Map([
    ['name','daji'],
    ['age',5]
])
console.log(map);
console.log(map.size);
console.log(map.has('name')); //true
console.log(map.has('age')); //true
map.set('name','zhangsan')
console.log(map);  //name的value被覆盖为zhangsan
遍历方法
let map=new Map([
    ['name','daji'],
    ['age',5]
])
//第一个参数是value,第二个参数是key
map.forEach((value,key) => {
    console.log(value,key);
});
//第一个参数是key,第二个参数是value
for(let [key,value] of map){
    console.log(key,value);
}
for(let key of map.keys()){
    console.log(key);
}
for(let value of map.values()){
    console.log(value);
}
for(let [key,value] of map.entries()){
    console.log(key,value);
}
应用场景
  • Object对象的应用场景都能使用Map,且Map对键值对的增删改查性能更好
  • WeakMap(键名只支持引用数据类型,例如对象数组function)
let wm=new WeakMap()
wm.set([1],2)
wm.set({
    name:'daji'
},'es')
console.log(wm);
// wm.clear() //报错不支持clear方法
// wm.size() //报错不支持size方法 wm也不支持遍历 

//弱引用 引用次数不会增加 若当前h1dom元素被删除,垃圾机制也不会回收,会自动消失,有助于防止内存泄漏
let wm1=new WeakMap()
let elem=document.getElementsByTagName('h1')
wm1.set(elem,'info')
console.log(wm1.get(elem));

相关文章

网友评论

    本文标题:ES6新特性Symbol,Set,Map

    本文链接:https://www.haomeiwen.com/subject/mpejqltx.html