JavaScript性能优化之小知识总结(4)

//糟糕的全局变量和全局函数 var current = null; function init(){ //... } function change() { //... } function verify() { //... } //解决办法有很多,Christian Heilmann建议的方法是: //如果变量和函数不需要在“外面”引用,那么就可以使用一个没有名字的方法将他们全都包起来。 (function(){ var current = null; function init() { //... } function change() { //... } function verify() { //... } })(); //如果变量和函数需要在“外面”引用,需要把你的变量和函数放在一个“命名空间”中 //我们这里用一个function做命名空间而不是一个var,因为在前者中声明function更简单,而且能保护隐私数据 myNameSpace = function() { var current = null; function init() { //... } function change() { //... } function verify() { //... } //所有需要在命名空间外调用的函数和属性都要写在return里面 return { init: init, //甚至你可以为函数和属性命名一个别名 set: change }; };

尊重对象的所有权

因为JavaScript可以在任何时候修改任意对象,这样就可以以不可预计的方式覆写默认的行为,所以如果你不负责维护某个对象,它的对象或者它的方法,那么你就不要对它进行修改,具体一点就是说:

不要为实例或原型添加属性
不要为实例或者原型添加方法
不要重定义已经存在的方法
不要重复定义其它团队成员已经实现的方法,永远不要修改不是由你所有的对象,你可以通过以下方式为对象创建新的功能:
创建包含所需功能的新对象,并用它与相关对象进行交互
创建自定义类型,继承需要进行修改的类型,然后可以为自定义类型添加额外功能

循环引用

如果循环引用中包含DOM对象或者ActiveX对象,那么就会发生内存泄露。内存泄露的后果是在浏览器关闭前,即使是刷新页面,这部分内存不会被浏览器释放。

简单的循环引用:

var el = document.getElementById('MyElement'); var func = function () { //… } el.func = func; func.element = el;

但是通常不会出现这种情况。通常循环引用发生在为dom元素添加闭包作为expendo的时候。

function init() { var el = document.getElementById('MyElement'); el.onclick = function () { //…… } } init();

init在执行的时候,当前上下文我们叫做context。这个时候,context引用了el,el引用了function,function引用了context。这时候形成了一个循环引用。

下面2种方法可以解决循环引用:

1)  置空dom对象

function init() { var el = document.getElementById('MyElement'); el.onclick = function () { //…… } } init(); //可以替换为: function init() { var el = document.getElementById('MyElement'); el.onclick = function () { //…… } el = null; } init();

将el置空,context中不包含对dom对象的引用,从而打断循环应用。

如果我们需要将dom对象返回,可以用如下方法:

function init() { var el = document.getElementById('MyElement'); el.onclick = function () { //…… } return el; } init(); //可以替换为: function init() { var el = document.getElementById('MyElement'); el.onclick = function () { //…… } try { return el; } finally { el = null; } } init();

2)  构造新的context

function init() { var el = document.getElementById('MyElement'); el.onclick = function () { //…… } } init(); //可以替换为: function elClickHandler() { //…… } function init() { var el = document.getElementById('MyElement'); el.onclick = elClickHandler; } init();

把function抽到新的context中,这样,function的context就不包含对el的引用,从而打断循环引用。

通过javascript创建的dom对象,必须append到页面中

IE下,脚本创建的dom对象,如果没有append到页面中,刷新页面,这部分内存是不会回收的!

function create() { var gc = document.getElementById('GC'); for (var i = 0; i < 5000; i++) { var el = document.createElement('div'); el.innerHTML = "test"; //下面这句可以注释掉,看看浏览器在任务管理器中,点击按钮然后刷新后的内存变化 gc.appendChild(el); } }

释放dom元素占用的内存

将dom元素的innerHTML设置为空字符串,可以释放其子元素占用的内存。

在rich应用中,用户也许会在一个页面上停留很长时间,可以使用该方法释放积累得越来越多的dom元素使用的内存。

释放javascript对象

在rich应用中,随着实例化对象数量的增加,内存消耗会越来越大。所以应当及时释放对对象的引用,让GC能够回收这些内存控件。

对象:obj = null

对象属性:delete obj.myproperty

数组item:使用数组的splice方法释放数组中不用的item

避免string的隐式装箱

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wgzjgs.html