Web 技术研究所

我一直坚信着,Web 将会成为未来应用程序的主流

DOM元素的唯一性

  无论你以何种方式来获取DOM元素,只要他们是同一个,句柄就必定是唯一的。所以,我们经常利用DOM的Property来存放自己的数据。因为即使释放了用来存放DOM句柄的变量也可以从文档中再次获取到这个DOM,存放在上面的数据不会因为换了个引用就丢失。
  这东西也许看似是入门级的知识吧?确实刚学JavaScript的时候不会怀疑这个问题。因为那时候甚至不知道Property和Attribute的区别。但是知道的东西越多,怀疑的东西也就越多。为什么DOM元素的Property不会因为自身引用的释放而被GC回收呢?内存的回收机制是不允许有例外的,那么唯一能解释这个现象的只有对象引用没被释放干净了。也就是说,DOM对象除了我们的变量外还被其它东西引用着。这引用它的就是DOM树,可以从下面这个测试中证明。 <div></div>
<script>
onload=function(){
  //文档加载完成时给div绑定一个20M的数据
  var div=document.getElementsByTagName("div")[0];
  div.data=Array((1<<20)*20).join(" ");
};
document.onclick=function(){
  //点击文档时把这个div从文档中卸下来
  var div=document.getElementsByTagName("div")[0];
  console.log(div.data.length);
  document.body.removeChild(div);
};
</script>

  大概在22秒时我点击了文档,所以这个20M的内存是在我点击之后才被释放的。在文档加载完成到我点击文档的这段期间,我们并没有对div元素的直接引用,onload中使用的也是局部变量,在onload执行完后局部变量的引用就会被释放。但是无论如何,div依然被DOM树引用着,直到我点击文档后才把它从DOM树中移除。这就意味着,DOM树对元素的储存是按元素句柄储存的,任何元素在DOM树中都有唯一性。无论你的元素是以何种方式从文档中获取的,它获取的都是内存中的对象,而不是从HTML中构造一个出来。
  不要把这个测试误解成“只要从文档中移除就会释放内存”,从文档中移除是释放内存的必要条件,但不是充分条件。应该是“取消包括文档在内的所有引用才会释放DOM对象的内存”,如果我把上面代码onclick中的div声明成全局变量,在点击之后元素确实会被从文档中移除。但是内存依然不会释放,因为有个全局变量在应用着它。当然,如果这时候再点击一次文档代码就出错了,因为已经从文档中移除了对象getElementsByTagName就无法获取到了。JavaScript的GC机制本身是的基础部分,如果不明白的话我下回再好好说下这玩意儿。这篇文章要说明的只是DOM树对DOM对象引用的唯一性问题。
网名:
3.80.55.*
电子邮箱:
仅用于接收通知
提交 悄悄的告诉你,Ctrl+Enter 可以提交哦
神奇海螺
[查看全部主题]
各类Web技术问题讨论区
发起新主题
本模块采用即时聊天邮件通知的模式
让钛合金F5成为历史吧!
次碳酸钴的技术博客,文章原创,转载请保留原文链接 ^_^