ES6提供的 Set 【WeakSet】 和 Map 【WeakMap】 数据结构

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>ES6提供的 Set 【WeakSet】 和 Map 【WeakMap】 数据结构</title>
    </head>
    <body>
        <script type="text/javascript">
            /*
                基本类型: String、Number、Boolean、Null、Undefined、Symbol  【typeof 检测基本类型】
                引用类型:对象(Object)、数组(Array)、函数(Function)
            */
            // js基本数据类型
            let a = undefined
            console.log(typeof a) // undefined
            let b = null
            console.log(typeof b) // object
            let c = 1
            console.log(typeof c) // number
            let d = true
            console.log(typeof d) // boolean
            let e = 'abc'
            console.log(typeof e) // string
            // 可以用在一个整数字面量后面加 n 的方式定义一个 BigInt ,如:10n,或者调用函数BigInt()
            // BigInt 是一种内置对象,它提供了一种方法来表示大于 2^53 - 1 的整数。这原本是 Javascript中可以用 Number 表示的最大数字
            // BigInt 可以表示任意大的整数
            // BigInt 和 Number 不是严格相等的,但是宽松相等的
            const f = 10n;
            console.log(f, typeof f) // 10n "bigint"
            const g = BigInt(10)
            console.log(g, typeof g) // 10n "bigint"
            console.log(0n === 0) // false
            console.log(0n == 0) // true
            // 每个从Symbol()返回的symbol值都是唯一的。一个symbol值能作为对象属性的标识符;这是该数据类型仅有的目的
            const sy = Symbol();
            const sy1 = Symbol(42);
            console.log(typeof sy, sy1) // symbol  Symbol(42)
            console.log(Symbol(1) === Symbol(1)) // false
            
            // 引用数据类型
            let obj = new Object // 等价 new Object() 无参数()可省略
            console.log(obj, obj instanceof Object) // {} true
            // Object.create()方法创建一个新对象,使用现有的对象来提供新创建的对象的__proto__
            console.log(Object.create({}))
            let arr = new Array
            console.log(arr, arr instanceof Object, typeof arr) // [] true  object
            
            // 用 Object.create实现类式继承
            // ParentClass - 父类(superclass)
            function ParentClass() {
              this.x = 0;
              this.y = 0;
            }
            // 父类的方法
            ParentClass.prototype.move = function(x, y) {
              this.x += x;
              this.y += y;
              console.info('ParentClass is change.');
            };
            // ChildClass - 子类(subclass)
            function ChildClass() {
              ParentClass.call(this); // call super constructor.
            }
            // 子类续承父类
            ChildClass.prototype = Object.create(ParentClass.prototype);
            ChildClass.prototype.constructor = ChildClass;
            let newObj = new ChildClass()
            console.log(newObj, newObj instanceof Object) // ChildClass {x: 0, y: 0} true
            console.log(newObj, newObj instanceof ParentClass) // ChildClass {x: 0, y: 0} true
            newObj.move(2,2) // ParentClass is change.
            
            let fn  = function(){
                console.log(this)
            } 
            console.log(fn, fn instanceof Object, typeof fn) // f(){console.log(this)} true  function
            // constructor判断            
            console.log([] instanceof Array);//->true
            console.log(/^$/ instanceof RegExp);//->true
            console.log([] instanceof Object);//->true
            console.log([].constructor === Array);//->true
            console.log([].constructor === Object);//->false 我们的constructor可以避免instanceof检测的时候,用Object也是true的问题
            console.log({}.constructor === Object); // true
            /*
            Array.isArray() ECMAScript5将Array.isArray()正式引入JavaScript,目的就是准确地检测一个值是否为数组 IE8不支持
            两个或者多个typeof一起使用时,返回值一定是"string";
            检测的不管是数组还是正则都返回的是"object",所以typeof不能判断一个值是否为数组
            Object.prototype.toString.call(value)  判断某个对象值属于哪种内置类型
            */
           
            // 接下来谈下这个 ES6中的Set 和 Map 数据结构
            // Set 数据结构
            let mySet = new Set()
            console.log(mySet,typeof mySet)  // Set(0){} "object"
            mySet.add(1)
            mySet.add(2)
            mySet.add(2)
            mySet.add(3)
            console.log(mySet) // Set(3){1,2,3}
            let setTest = new Set([1,2,3,4,5,5,6,6])
            let setArr = [...setTest]
            console.log(setTest) // Set(3){1,2,3,4,5,6}
            console.log(setArr) // [1, 2, 3, 4, 5, 6]
            // 结论
            /*
                Set 数据结构 类似于数组但是Set不会添加重复的值
                Set 加入值的时候,不会发生类型转换
                [...new Set(array)] 可以去除数组重复成员的方法
                [...new Set('string')].join('') 可以去除字符串里面的重复字符
                Set函数可以接受一个数组(或者具有 iterable 接口的其他数据结构)作为参数,用来初始化
                Array.from方法可以将 Set 结构转为数组 【Array.from是将类数组转为数组的一种方法】
                将类数组转为数组的方法:
                    1、Array的slice方法 例如:let arr = Array.prototype.slice.call(arguments);
                    2、Array.from() 例如:let arr = Array.from(arguments); 只要有length属性的对象,都可以应用此方法转换成数组
                    3、扩展运算符... 例如:let arr = [...arguments];  这种数据结构必须有遍历器接口
                    4、jquery的$.makeArray() 例如:let arr = $.makeArray(arguments);
                    使用Array的slice方法,此方法如果不传参数的话会返回原数组的一个拷贝,因此可以用此方法转换类数组到数组
                    let arr = Array.prototype.slice.call(arguments);
                        // 等同于
                    let arr = [].slice.call(arguments)
            */
           
           // WeakSet 数据结构
           const myWeakSet = new WeakSet();
           // myWeakSet.add(1) // 报错 Invalid value used in weak set
           console.log(myWeakSet,typeof myWeakSet) // WeakSet {} "object"
           const arrs = [[1, 2], [3, 4]];
           const ws = new WeakSet(arrs);
           console.log(ws) // WeakSet {[1, 2], [3, 4]}
           // 结论
            /*
                WeakSet 结构与 Set 类似,也是不重复的值的集合
                WeakSet 的成员只能是对象,而不能是其他类型的值
                WeakSet 中的对象都是弱引用,即垃圾回收机制不考虑 WeakSet 对该对象的引用,
                如果其他对象都不再引用该对象,那么垃圾回收机制会自动回收该对象所占用的内存
                WeakSet 没有size属性 ES6 规定 WeakSet 不可遍历
            */
           
           // Map 数据结构
           const mp = new Map();
           console.log(mp,typeof mp) // Map(0) {} "object"
           const items = [
                ['name', '小明'],
                ['age', 28]
            ]
           items.forEach(
             ([key, value]) => mp.set(key, value)
           )
           console.log(mp) // Map(2) {"name" => "小明", "age" => 28}
           
           const map = new Map();
               map.set(1, 'aaa').set(1, 'bbb')
            console.log(map,map.get(1)) // Map(1) {1 => "bbb"}   'bbb'
            const mapTest = new Map([
              [1, 'one'],
              [2, 'two'],
              [3, 'three'],
            ])
            console.log([...mapTest.keys()]) // [1, 2, 3]
            console.log([...mapTest.values()]) // ['one', 'two', 'three']
            console.log([...mapTest.entries()]) // [[1,'one'], [2, 'two'], [3, 'three']]
            console.log([...mapTest]) // [[1,'one'], [2, 'two'], [3, 'three']]
           // 结论
           /*
                对同一个键多次赋值,后面的值将覆盖前面的值
                读取【get方法】一个未知的键,则返回undefined
                只有对同一个对象的引用,Map 结构才将其视为同一个键
                同样的值的两个实例,在 Map 结构中被视为两个键
                Map 的键实际上是跟内存地址绑定的,只要内存地址不一样,就视为两个键
                Object 结构提供了“字符串—值”的对应,Map 结构提供了“值—值”的对应,是一种更完善的 Hash 结构实现。
                如果你需要“键值对”的数据结构,Map 比 Object 更合适
                任何具有 Iterator 接口、且每个成员都是一个双元素的数组的数据结构都可以当作Map构造函数的参数, Set和Map都可以用来生成新的 Map
                Map 结构转为数组结构,比较快速的方法是使用扩展运算符(...)
           */
          
            // WeakMap 数据结构
            const wmp = new WeakMap();
            console.log(wmp, typeof wmp) // WeakMap {} "object"
            let key = {age: 1}
            console.log(wmp.set(key,20)) // WeakMap {{…} => 20}
            console.log(wmp.get(key)) // 20
            // 结论 【WeakMap与Map的区别有两点】
            /*
                WeakMap只接受对象作为键名(null除外),不接受其他类型的值作为键名
                WeakMap的键名所指向的对象,不计入垃圾回收机制
                如果你要往对象上添加数据,又不想干扰垃圾回收机制,就可以使用 WeakMap
                WeakMap的专用场合就是,它的键所对应的对象,可能会在将来消失。WeakMap结构有助于防止内存泄漏
                WeakMap 弱引用的只是键名,而不是键值。键值依然是正常引用
                WeakMap 的另一个用处是部署私有属性 class _xx开头的
            */
        </script>
    </body>
</html>

 

posted @ 2021-03-10 10:10  鱼樱前端  阅读(112)  评论(0编辑  收藏  举报