服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

node.js|vue.js|jquery|angularjs|React|json|js教程|

服务器之家 - 编程语言 - JavaScript - js教程 - 一个关于JS操作符in问题引发的探究

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

2022-02-28 16:44恪愚 js教程

这篇文章主要给大家介绍了一个JS操作符in问题引发的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

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

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

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

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

  1. <div id="root"
  2.     <div class="child">我是子元素</div> 
  3.     <button>移除</button> 
  4. </div> 
  5. <script> 
  6.     let btn = document.querySelector('button'
  7.     let child = document.querySelector('.child'
  8.     let root = document.querySelector('#root'
  9.      
  10.     btn.addEventListener('click'function() { 
  11.         root.removeChild(child) 
  12.     }) 
  13.  
  14. </script> 

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

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

  1. <div id="root"
  2.     <div class="child">我是子元素</div> 
  3.     <button>移除</button> 
  4. </div> 
  5. <script> 
  6.     let btn = document.querySelector('button'
  7.  
  8.     btn.addEventListener('click'function() {   
  9.         let child = document.querySelector('.child'
  10.         let root = document.querySelector('#root'
  11.  
  12.         root.removeChild(child) 
  13.     }) 
  14.  
  15. </script> 

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

点按钮的情况…)。

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

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

怎么判断?

遍历?不,太过麻烦!

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

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

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

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

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

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

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

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

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

然后

  1. console.log(child in p_child); 

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

!!!

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

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

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

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

没错啊!

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

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

???

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

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

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

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

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

这验证了我们的结论。

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

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

  1. <div id="root"
  2.     <div class="child">我是子元素</div> 
  3.     <button>移除</button> 
  4. </div> 
  5. <script> 
  6.     let btn = document.querySelector('button'
  7.     let child = document.querySelector('.child'
  8.     let root = document.querySelector('#root'
  9.     let r_child = [...root.children] 
  10.      
  11.     btn.addEventListener('click'function() { 
  12.         if(r_child.includes(child)){   // 或者你这里直接判断child是否为null也可以...吧 
  13.             root.removeChild(child) 
  14.         } 
  15.     }) 
  16.  
  17. </script> 

略显仓促的结尾

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

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

总结

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

原文链接:https://blog.csdn.net/qq_43624878/article/details/115591008

延伸 · 阅读

精彩推荐
  • js教程JS实现纸牌发牌动画

    JS实现纸牌发牌动画

    这篇文章主要为大家详细介绍了JS实现纸牌发牌动画,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    计算机的皇帝5432022-01-04
  • js教程javascript实现倒计时关闭广告

    javascript实现倒计时关闭广告

    这篇文章主要为大家详细介绍了javascript实现倒计时关闭广告,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    爱前端的茂茂11612022-01-20
  • js教程js实现弹框效果

    js实现弹框效果

    这篇文章主要为大家详细介绍了js实现弹框效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    程序猿余某人3962022-02-20
  • js教程JavaScript快速实现日历效果

    JavaScript快速实现日历效果

    这篇文章主要为大家详细介绍了JavaScript快速实现日历效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    云杰8了10872022-02-13
  • js教程JS一分钟在github+Jekyll的博客中添加访问量功能的实现

    JS一分钟在github+Jekyll的博客中添加访问量功能的实现

    这篇文章主要介绍了JS一分钟在github+Jekyll的博客中添加访问量功能的实现,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借...

    董哥大鸟走四方6172022-02-22
  • js教程原生JS实现pc端轮播图效果

    原生JS实现pc端轮播图效果

    这篇文章主要为大家详细介绍了原生JS实现pc端轮播图效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    qq_1519846510212021-12-15
  • js教程js 执行上下文和作用域的相关总结

    js 执行上下文和作用域的相关总结

    这篇文章主要介绍了js 执行上下文和作用域的相关知识总结,帮助大家更好的理解和使用JavaScript,感兴趣的朋友可以了解下...

    前端Serendipity11292022-01-19
  • js教程玩转 Mockjs,前端也能跑得很溜

    玩转 Mockjs,前端也能跑得很溜

    mockjs作用就是,生成随机模拟数据,拦截 ajax 请求,可以对数据进行增删改查。在生成数据时,我们就需要能够熟练使用 mock.js 的语法。...

    前端人4882022-01-05