首页前端开发JavaScript一个关于JS操作符in问题引发的探究

一个关于JS操作符in问题引发的探究

时间2024-02-01 10:18:02发布访客分类JavaScript浏览735
导读:收集整理的这篇文章主要介绍了一个关于JS操作符in问题引发的探究,觉得挺不错的,现在分享给大家,也给大家做个参考。 事情是这样的:大家都知道“内存泄露”这回事吧。它有几个常见的场景:...
收集整理的这篇文章主要介绍了一个关于JS操作符in问题引发的探究,觉得挺不错的,现在分享给大家,也给大家做个参考。

事情是这样的:大家都知道“内存泄露”这回事吧。它有几个常见的场景:

  • 闭包使用不当引起内存泄漏
  • (未声明的)全局变量
  • 分离的DOM节点
  • (随意的)控制台的打印
  • 遗忘的定时器
  • 循环引用

内存泄漏需要重视,它是如此严重甚至会导致页面卡顿,影响用户体验!

其中第 3 点引起了我的注意 —— 我当然清楚地知道它说的是比如:“假设你手动移除了某个dom节点,本应释放该dom节点所占用的内存,但却因为疏忽导致某处代码仍对该被移除节点有引用,最终导致该节点所占内存无法被释放”的情况

div id="root">
        div class="child">
    我是子元素/div>
        button>
    移除/button>
    /div>
    script>
    let BTn = document.querySelector('button')    let child = document.querySelector('.child')    let root = document.querySelector('#root')        btn.addEventListener('click', function() {
        root.removeChild(child)    }
    )/script>
    

该代码所做的操作就是点击按钮后移除.child的节点,虽然点击后,该节点确实从dom被移除了,但全局变量child仍对该节点有引用,所以导致该节点的内存一直无法被释放。

解决办法:我们可以将对.child节点的引用移动到click事件的回调函数中,那么当移除节点并退出回调函数的执行上文后就会自动清除对该节点的引用,自然也就不会存在内存泄漏的情况了。(这实际上是在事件中实时检测该节点是否存在,如果不存在则浏览器必不会触发remove函数的执行)

div id="root">
        div class="child">
    我是子元素/div>
        button>
    移除/button>
    /div>
    script>
    let btn = document.querySelector('button')    btn.addEventListener('click', function() {
          let child = document.querySelector('.child')        let root = document.querySelector('#root')        root.removeChild(child)    }
    )/script>
    

这段代码很完美么?不。因为它在每次事件触发后都创建了对child和root节点的引用。消耗了内存(你完全可以想象一些人会狂

点按钮的情况…)。

其实还有一种办法:我们在click中去判断当前root节点中是否还存在child子节点,如果存在,则执行remove函数,否则什么也不做!

这就引发了标题中所说的行为。

怎么判断?

遍历?不,太过麻烦!

不知怎的,我突然想到了 for...in 中的 in 操作符,它可以基于原型链遍历对象!

我们来还原一下当时的场景:打开GITHub,随便找一个父节点,并获取它:

@H_777_56@

图中画红框的就是我们要取的父元素,橘红色框的就是要判断是否存在的子元素。

let parent=document.querySelector('.position-relative');
    let child=document.querySelector('.PRogress-pjax-loader');
    

这里注意,因为获取到的是DOM节点(类数组对象),所以我们在操作前一定要先处理一下:

let p_child=[...parent.children];
    

然后

console.LOG(child in p_child);
    

!!!

为什么呢?(此时笔者还没有意识到事情的严重性)

我想,是不是哪里出了问题,用es6的includes API验证一下:

console.log(p_child.includes(child));
    

没错啊!

再用一般的数组验证一下:

???

此时,笔者才想起到MDN上查阅一番:

进而我发现:in操作符单独使用时它检测的是左侧的值(作为索引)对应的值是否在右侧的对象内部(属性 & 原型上)

回到上面的代码中,我们发现:

这验证了我们的结论。

很显然,“子元素”并不等同于“存在于原型链上” —— 这又引出了一个知识点:attribute和property的区别!

所以经过一番“折腾”,源代码还是应该直接这样写:

div id="root">
        div class="child">
    我是子元素/div>
        button>
    移除/button>
    /div>
    script>
    let btn = document.querySelector('button')    let child = document.querySelector('.child')    let root = document.querySelector('#root')    let r_child = [...root.children]        btn.addEventListener('click', function() {
        if(r_child.includes(child)){
   // 或者你这里直接判断child是否为null也可以...吧        	root.removeChild(child)        }
    }
    )/script>
    

略显仓促的结尾

所以,看书学习有时候并不能“不求甚解”~

还要勇于“折腾”,学会“查文档”[/滑稽脸].

总结

到此这篇关于一个关于JS操作符in问题的文章就介绍到这了,更多相关JS操作符in问题内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!

您可能感兴趣的文章:
  • javascript之typeof、instanceof操作符使用探讨

声明:本文内容由网友自发贡献,本站不承担相应法律责任。对本内容有异议或投诉,请联系2913721942#qq.com核实处理,我们将尽快回复您,谢谢合作!

上一篇: 一个关于JS正则匹配的踩坑记录下一篇:React Hooks常用场景的使用(小结...猜你在找的JavaScript相关文章 html font标签如何设置字体大小?html font标签属性用法介绍2022-05-16vue3+TypeScript+vue-router的使用方法2022-04-16vue3获取当前路由地址2022-04-16如何利用React实现图片识别App2022-04-16JavaScript展开运算符和剩余运算符的区别详解2022-04-16微信小程序中使用vant框架的具体步骤2022-04-16Vue elementUI表单嵌套表格并对每行进行校验详解2022-04-16如何利用Typescript封装本地存储2022-04-16微信小程序中wxs文件的一些妙用分享2022-04-16JavaScript的Set数据结构详解2022-04-16 其他相关热搜词更多phpjavapython程序员loadpost-format-gallery

若转载请注明出处: 一个关于JS操作符in问题引发的探究
本文地址: https://pptw.com/jishu/595270.html
ASP.NET+XML打造网络硬盘原理分析 ASP.NET设计网络硬盘之上传文件实现代码

游客 回复需填写必要信息