Set与WeakSet类型在JavaScript中的使用

set类型与array与object对比分析:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
    <style>

    </style>
</head>

<body>


    <script>
        // let arr = [1, 1, 1, 1, 1];
        // console.table(arr);

        // set集合
        // let set = new Set([1, 2, 3, 4, 5]);
        // console.log(set);

        // 区分类型,相同类型的不可重复
        // let set = new Set();
        // set.add(1);
        // set.add(1);
        // set.add('1');
        // console.log(set);

        // set和object的区别
        // 对象中:不同类型可隐式转换的也不可重复,否则前面的会被后面的覆盖
        // let obj = {
        //     1: 'cyy1',
        //     '1': 'cyy2'
        // };
        // console.log(obj);

        let obj = {
            1: 'cyy1',
            '1': 'cyy2'
        };
        // let cyy = {
        //     obj: 'yaya'
        // };
        // console.log(cyy.obj);
        // 变量需要用方括号
        let cyy = {
            [obj]: 'yaya'
        };
        // 对象作为属性名,会自动调用toString(),转为字符串
        console.log(cyy);//[object Object]
        console.log(obj.toString());
        console.log(cyy[obj.toString()]);
    </script>
</body>

</html>

set元素检测与管理:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
    <style>

    </style>
</head>

<body>


    <script>
        // let set = new Set('cyy');
        // console.log(set);
        // 字符串会转数组,且不可重复;相当于以下写法
        // let set = new Set([...'cyy']);
        // console.log(set);

        //通常还是用数组形式
        // 获取set长度
        let set = new Set([1, 2, 3]);
        console.log(set.size);
        // 判断set是否含有某个值
        console.log(set.has(1));
        console.log(set.has(11));
        // 删除set中的某个值
        set.delete(2);
        console.log(set);
        // 获取set的值
        console.log(set.values());
        // 清空set
        set.clear();
        console.log(set.size);
    </script>
</body>

</html>

类型之间互相帮助才是好兄弟:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
    <style>

    </style>
</head>

<body>


    <script>
        // set转数组
        // let set = new Set([1, 2, 3, 4]);
        // console.log(Array.from(set));
        // console.log([...set]);

        // let set = new Set('123456789');
        // let res = [...set].filter((item) => item < 5);
        // console.log(new Set(res));

        // 通过set帮助array去重
        let arr = [1, 2, 3, 5, 2, 4, 1];
        console.log([...new Set(arr)]);
    </script>
</body>

</html>

遍历set类型的方式:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
    <style>

    </style>
</head>

<body>


    <script>
        // set没有键名,key和value都是键值
        // let set = new Set([11, 22, 33, 44]);
        // console.log(set.keys());
        // console.log(set.values());
        // console.log(set.entries());

        let set = new Set([11, 22, 33, 44]);
        // set.forEach(function (value, index, arr) {
        //     console.log(value, index, arr);
        // });

        for (let value of set) {
            console.log(value);
        }
    </script>
</body>

</html>

使用set处理网站关键词:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
    <style>
        body {
            padding: 200px;
        }
        
        ul {
            list-style: none;
            padding: 0;
            margin: 0;
        }
        
        li {
            padding: 10px;
            border: 1px solid #ddd;
        }
    </style>
</head>

<body>
    <input type="text" name="keyword">
    <ul></ul>

    <script>
        // let obj = {
        //     data: new Set(),
        //     set keyword(value) {
        //         this.data.add(value);
        //     },
        //     show() {
        //         let ul = document.querySelector('ul');
        //         ul.innerHTML = '';
        //         this.data.forEach(function(value) {
        //             ul.innerHTML += `<li>${value}</li>`;
        //         });
        //     }
        // }

        // let input = document.querySelector('[name=keyword]');
        // input.addEventListener('blur', function() {
        //     obj.keyword = this.value;
        //     obj.show();
        // });


        let obj = {
            data: new Set(),
            keyword(value) {
                this.data.add(value);
            },
            show() {
                let ul = document.querySelector('ul');
                ul.innerHTML = '';
                this.data.forEach(function(value) {
                    ul.innerHTML += `<li>${value}</li>`;
                });
            }
        }

        let input = document.querySelector('[name=keyword]');
        input.addEventListener('blur', function() {
            obj.keyword(this.value);
            obj.show();
        });
    </script>
</body>

</html>

并集-交集-差集,算法实现

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
    <style>

    </style>
</head>

<body>

    <script>
        let a = new Set([1, 2, 3, 4, 5]);
        let b = new Set([4, 5, 9, 6]);
        // 并集
        console.log(new Set([...a, ...b]));
        // 差集,a有,b没有
        console.log(new Set([...a].filter(function(item) {
            return !b.has(item);
        })));
    </script>
</body>

</html>

WeakSet语法介绍:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
    <style>

    </style>
</head>

<body>
    <div></div>
    <div></div>

    <script>
        // WeakSet 跟 set 差不多,但是WeakSet的元素只能是引用类型
        // let set = new WeakSet([1, 2]);
        // let set = new WeakSet();
        // set.add([1, 2, 3]);

        let nodes = new WeakSet();
        let divs = document.querySelectorAll('div');
        divs.forEach(function(item) {
            // console.log(item);
            // WeakSet的元素可以是dom节点
            nodes.add(item);
        });
        console.log(nodes);

        // 删除元素
        nodes.delete(divs[0]);
        // nodes.delete(nodes[1]);
        console.log(nodes);

        // 判断是否含有元素
        console.log(nodes);
        console.log(nodes.has(divs[0]));
        console.log(nodes.has(divs[1]));
    </script>
</body>

</html>

引用类型的垃圾回收原理:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
    <style>

    </style>
</head>

<body>
    <div></div>
    <div></div>

    <script>
        let a = {
            name: 'cyy'
        };
        let b = a;
        let arr = [a]; //被引用第三次
        arr[0] = null; //解除该引用
        // 此时该内存地址被a引用一次,被b引用一次,共引用2次
        a = null;
        console.log(b);
        // 次数a的引用断开,该内存地址只被b引用1次
        b = null;
        // 此时该内存地址没有被引用,因此属于垃圾
        console.log(a, b);
        //系统会自动检测内存有没有被引用,没有的话会自动垃圾回收
    </script>
</body>

</html>

WeakSet弱引用类型:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
    <style>

    </style>
</head>

<body>


    <script>
        // WeakSet是弱引用类型,因此无法使用keys,values,以及迭代方法

        // WeakSet不会增加引用次数
        // let a = {
        //     name: 'cyy'
        // };
        // let b = a;
        // let set = new WeakSet();
        // set.add(a);
        // // 此时该内存被引用次数为2,
        // a = null;
        // b = null;
        // // 此时该内存没有被引用,但是WeakSet并不知情,导致WeakSet内显示空元素
        // console.log(set);

        // WeakSet的弱引用特性会导致循环出问题,因此无法进行循环操作
        // console.log(set.keys());
        // console.log(set.values());

        // let set = new WeakSet();
        // set.add([1, 2, 3]);
        // console.log(set.keys());
        // console.log(set.values());
        // for (const item of set) {
        //     console.log(item);
        // }
        // console.log(set.size);


        let a = {
            name: 'cyy'
        };
        let b = a;
        let set = new WeakSet();
        set.add(a);
        a = null;
        b = null;
        console.log(set);
        // WeakSet在一定时间之后,也是能够读取到被回收的垃圾,然后同步清空
        setTimeout(function() {
            console.log(set);
        }, 2000);
    </script>
</body>

</html>

todo任务列表中使用WeakSet:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
    <style>
        * {
            margin: 0;
            padding: 0;
        }
        
        body {
            padding: 200px;
        }
        
        ul {
            list-style: none;
        }
        
        li {
            width: 200px;
            border: 1px solid orange;
            position: relative;
            height: 40px;
            line-height: 40px;
            margin-bottom: 10px;
            padding: 10px;
        }
        
        li a {
            display: inline-block;
            color: white;
            position: absolute;
            right: 5px;
            top: 15px;
            background: green;
            border-radius: 5px;
            width: 30px;
            height: 30px;
            line-height: 30px;
            text-align: center;
            text-decoration: none;
        }
        
        li.remove {
            opacity: .1;
        }
    </style>
</head>

<body>
    <ul>
        <li>baidu.com
            <a href="javascript:;">x</a>
        </li>
        <li>google.com
            <a href="javascript:;">x</a>
        </li>
        <li>taobao.com
            <a href="javascript:;">x</a>
        </li>
    </ul>

    <script>
        class Todo {
            // 构造函数
            constructor() {
                this.items = document.querySelectorAll('li');
                // console.log(this.items);

                this.lists = new WeakSet();
                // 只能用箭头函数,因为this指向不能变
                this.items.forEach((item) => this.lists.add(item));
                console.log(this.lists);
            }
            run() {
                this.addEvent();
            }
            addEvent() {
                this.items.forEach((item) => {
                    let a = item.querySelector('a');
                    // 只能用箭头函数,因为this指向不能变
                    a.addEventListener('click', (e) => {
                        // console.log(e.target);
                        let li = e.target.parentElement;
                        if (this.lists.has(li)) {
                            li.classList.add('remove');
                            this.lists.delete(li);
                        } else {
                            // 提示已删除
                            // alert('todo已经删除');

                            // 恢复被删除的
                            li.classList.remove('remove');
                            this.lists.add(li);
                        }
                    })
                })
            }
        }
        new Todo().run();
    </script>
</body>

</html>

原文地址:https://www.cnblogs.com/chenyingying0/p/13991767.html