一篇文章带你搞懂JS对象的自我销毁

在日常的JS组件开发中,往往会有一些较为复杂的DOM操作及事件监听,尤其是在处理UI层面的widgets时候更为明显。常常会花很多精力在对象的init上,而当组件需要被移除时则仅仅是把所在DOM草草的remove掉就算完事儿。

当然,绝大多数情况这样处理并没有什么不妥,因为事件监听时仅仅局限于所属的DOM自身,移除DOM后,只要对象的外部引用不再维系,相关的内存占用很快就会被当作垃圾回收掉(本文不讨论低版本 IE 内存回收的 BUG)。

其实个人在构建组件(对象)的时候是比较习惯于添加自定义方法destroy,用来手动销毁对象内部的一些引用。也就是今天要说的仅靠移除DOM并不能达到销毁对象的几种情况。

当你的组件出现下面几种情况时需要特别注意。

一: DOM事件监听越界
常规情况下,一个组件需要监听的仅仅是自身的DOM内的事件。偶尔也会有另一种情况,对象不得不操作自身之外的DOM。

拿常见的瀑布流组件为例,除了自身事件,还要监听页面的滚动、浏览器尺寸重置等事件。因此当瀑布流组件需要被移除时,简单的移除自身DOM并不能完整销毁组件对页面的影响。

下面是常规做法的例子:

//定义瀑布流组件
function WaterFall(node){
  this.node = node;
  window.addEventListener(‘scroll‘,function(){
    //do sth
    console.log(‘scrolling‘);
  });
}
//实例化一个瀑布流组件
var node_content = document.getElementById(‘xxx‘);
new WaterFall(node_content);
//移除瀑布流组件所属的DOM
node_content.parentNode.removeChild(node_content);

上面的例子很明显,移除DOM后遗留的事件监听还在,回调内对组件的引用会导致整个组件常驻内存无法被回收,直至页面卸载。

不过你可能会说,在移除DOM时顺手解除下事件绑定就 OK 啦。事实确实如此,但是如果操作的具体细节让调用者实现就有点儿麻keng烦die了。因此我们需要提供一个destroy接口让调用者去解除对窗口滚动等事件的监听。

//定义瀑布流组件
function WaterFall(node){
  this.node = node;
  this._scrollListenner = function(){
    //do sth
    console.log(‘scrolling‘);
  };
  window.addEventListener(‘scroll‘,this._scrollListenner);
}                                                   //欢迎加入前端全栈开发交流圈一起学习交流:1007317281
WaterFall.prototype.destroy = function(){
    window.removeEventListener(‘scroll‘,this._scrollListenner);
    this.node.parentNode.removeChild(this.node);
};

//实例化一个瀑布流组件
var myWaterFall = new WaterFall(document.getElementById(‘xxx‘));
//注销瀑布流组件
myWaterFall.destroy();

给大家推荐一个技术交流学习圈,里面概括移动应用网站开发,css,html,webpack,vue node angular以及面试资源等。**获取资料

原文地址:https://blog.51cto.com/14145734/2391961

时间: 2024-10-11 10:46:57

一篇文章带你搞懂JS对象的自我销毁的相关文章

一篇文章带你搞懂spring全家桶套餐

spring全家桶里都有哪些食物 上期我们讲了spring和springmvc两个框架的基础知识和学习路线,而这期内容,我们将围绕着spring全家桶展开来讨论. 大家应该都知道,按照出现的顺序,spring全家桶大概包含了spring.springmvc.springboot以及springcloud,从开胃小菜spring到满汉全席springcloud,spring全家桶可谓Java工程师的必备大餐,那么,我们不妨先来看看,spring全家桶是如何从光杆司令spring发展到如今的庞大家族

一篇文章带你搞懂DEX文件的结构

DEX文件就是Android Dalvik虚拟机运行的程序,关于DEX文件的结构的重要性我就不多说了.下面,开练! 建议:不要只看,跟着我做.看再多遍不如自己亲自实践一遍来的可靠,别问我为什么知道.泪崩ing..... 首先,我们需要自己构造一个dex文件,因为自己构造的比较简单,分析起来比较容易.等你简单的会了,难的自然也就懂了. 0x00■  构造DEX文件 首先,我们编写一个简单的Java程序,如下: public class HelloWorld { int a = 0; static

一篇文章带你看懂Cloudflare信息泄露事件

版权声明:本文由贺嘉  原创文章,转载请注明出处: 文章原文链接:https://www.qcloud.com/community/article/753847001488039974 来源:腾云阁 https://www.qcloud.com/community 1.问题描述 近期根据Hacker News的报道,以及国际CDN厂商cloudflare的公告,我们注意到了一起敏感信息.API 密钥被Cloudflare泄露给了随机的 requesters请求,同时相关敏感数据也被搜索引擎给收录

一篇文章带你看懂AWS re:Invent 2018大会,揭秘Amazon Aurora

本文由云+社区发表 | 本文作者: 刘峰,腾讯云NewSQL数据库产品负责人.曾职于联想研究院,Teradata北京研发中心,从事数据库相关工作8年.2017年加入腾讯数据库产品中心,担任NewSQL数据库产品负责人. 云数据库与传统数据库的战争已打响,一个字概括就是"抢". 如火如茶的 AWS re:Invent 2018大会闭幕了,相信云养鹅的产品经理们又准时打开油管,Recap一年一度的科技盛宴. 据说今年一共发布了140多项产品服务,但是,Amazon Aurora 数据库 仍

精辟:一篇文章带你看懂数据储存!

前言:日益火热的云服务 小米组织架构调整上了热搜,如同阿里巴巴.华为和腾讯一样,小米组织架构调整中也将云平台单独成为一个部门.自2018年以来,各大企业调整组织架构的动作中,其实可以窥见大企业对云平台的重视程度,云服务在很多方面悄悄的改变了人们的生活,不过由于消费端接触不多,大家对云服务内容认识较少. 数据储存是云服务中较为重要的板块,早期百度.腾讯.微博.金山等企业都推出自己的免费云盘,供给用户使用,这也是我们最早接触云储存,随着云计算技术的成熟,云服务更偏重于为企业提供服务,基于云计算,搭建

一篇文章带你了解spring框架

虽然现在流行用SpringBoot了,很多配置已经简化和封装了,但是对于Spring的一些基础我们了解一些是对我们自己的架构思想很有帮助的!接下来和笔者一起来探讨一下Spring框架吧! 1.什么是Spring框架?Spring框架有哪些主要模块? Spring框架是一个为Java应用程序的开发提供了综合.广泛的基础性支持的Java平台.Spring帮助开发者解决了开发中基础性的问题,使得开发人员可以专注于应用程序的开发.Spring框架本身亦是按照设计模式精心打造,这使得我们可以在开发环境中安

面试官最喜欢问的CAS还不会?怎么和他吹牛?!一文带你搞懂CAS

后端开发中大家肯定遇到过实现一个线程安全的计数器这种需求,根据经验你应该知道我们要在多线程中实现?共享变量?的原子性和可见性问题,于是锁成为一个不可避免的话题,今天我们讨论的是与之对应的无锁 CAS.本文会从怎么来的.是什么.怎么用.原理分析.遇到的问题等不同的角度带你真正搞懂 CAS. 为什么要无锁 我们一想到在多线程下保证安全的方式头一个要拎出来的肯定是锁,不管从硬件.操作系统层面都或多或少在使用锁.锁有什么缺点吗?当然有了,不然 JDK 里为什么出现那么多各式各样的锁,就是因为每一种锁都有

一篇文章带你了解JavaScript中的面向 “对象”

作者 | Jeskson 来源 | 达达前端小酒馆 安装webpack,打包工具,安装webpack-dev-server,安装babel解析es6语法,初始化npm环境. npm install webpack webpack-cli --save-dev webpack.dev.config.js module.exports = { entry: './src/index.js', output: { path: __dirname, filename: './release/bundle

一篇文章带你了解JavaScript中的函数表达式,递归,闭包,变量,this对象,模块作用域

作者 | Jeskson 来源 | 达达前端小酒馆 定义函数的方式: 第一种为 函数声明: 第二种为 函数表达式. 语法: function functionName(arg0, arg1, arg2) { // 函数体 } 在Firefox,Safari,Chrome和Opera有效: 就是通过这个属性可以访问到这个函数指定的名字. console.log(functionName.name); // 'functionName' 函数声明: 它的一个重要特点就是:函数声明提升,就是在执行代码