JavaScript 高效运行代码分析(6)

有些 DOM 集合是实时的,如果在你的脚本遍历列表时相关元素产生变化,则此集合会立刻变化而不需要等待脚本遍历结束。childNodes 集合和 getElementsByTagName 返回的节点列表都是这样的实时集合。

如果在遍历这样的集合的同时向其中添加元素,则可能会遇到无限循环,因为你不停的向列表中添加元素,永远也不会碰到列表结束。这不是唯一的问题。为提高性能,可能会对这些集合做出优化,如记住其长度、记住脚本中上一个访问元素序号,这样在你访问下一个元素时可快速定位。

如果你此时修改 DOM 树,即使修改的元素不在此集合中,集合还是会重新搜索以查看是否有新元素。这样就无法记住上一个访问元素序号或记住集合长度,因为集合本身可能已经变了,这样就无法使用优化:

var allPara = document.getElementsByTagName('p'); for( var i = 0; i < allPara.length; i++ ) { allPara[i].appendChild(document.createTextNode(i)); }

下面的代码在 Opera 和 Internet Explorer 等主流浏览器中比上面代码快10倍以上。先创建一个要修改元素的静态列表,然后遍历静态列表并作出相应修改,而不是遍历 getElementsByTagName 返回的节点列表:

var allPara = document.getElementsByTagName('p'); var collectTemp = []; for( var i = 0; i < allPara.length; i++ ) { collectTemp[collectTemp.length] = allPara[i]; } for( i = 0; i < collectTemp.length; i++ ) { collectTemp[i].appendChild(document.createTextNode(i)); } collectTemp = null; 使用变量保存 DOM 值

有些 DOM 返回值无法缓存,每次调用时都会重新调用函数。如 getElementById 方法。下面是一个低效率代码的例子:

复制代码 代码如下:

document.getElementById('test').property1 = 'value1'; document.getElementById('test').property2 = 'value2'; document.getElementById('test').property3 = 'value3'; document.getElementById('test').property4 = 'value4';

此代码为定位同一个对象调用了四次 getElementById 方法。下面的代码只调用了一次并将结果保存在变量中,单看这一个操作可能比上面单个操作要略慢,因为需要执行赋值语句。但后面不再需要调用 getElementById 方法!下面的代码比上面的代码要快5-10倍:

复制代码 代码如下:

var sample = document.getElementById('test'); sample.property1 = 'value1'; sample.property2 = 'value2'; sample.property3 = 'value3'; sample.property4 = 'value4';

页面载入 避免保存来自其他文档的引用

如果文档访问过其他文档中的节点或对象,在脚本结束后避免保留这些引用。如果在全局变量或对象属性中保存过这些引用,通过设置为 null 清除之或者直接删除之。

原因是另一个文档被销毁后,如弹出窗口被关闭,尽管那个文档已经不再了,所有对那个文档中对象的引用都会在内存中保存整个 DOM 树和脚本环境。这也适用那些包含在frame,内联 frame,或 OBJECT 元素中的网页。.

复制代码 代码如下:

var remoteDoc = parent.frames['sideframe'].document; var remoteContainer = remoteDoc.getElementById('content'); var newPara = remoteDoc.createElement('p'); newPara.appendChild(remoteDoc.createTextNode('new content')); remoteContainer.appendChild(newPara); //remove references remoteDoc = null; remoteContainer = null; newPara = null;

快速历史浏览(history navigation)

Opera (和许多其他浏览器)默认使用快速历史浏览。当用户点击后退或前进时,将记录当前页面的状态及页面中的脚本。当用户回到刚才的页面时,将立即显示刚才的页面,如同从没有离开此页一样。不需要重新载入页面也不需要重新初始化。脚本继续运行,DOM也和离开此页前完全相同。对用户来说这样反应很快,载入较慢的网页应用程序会有更好的性能。

尽管 Opera 提供开发者控制此行为的方式,最好还是尽量保持快速历史浏览功能。也就是说最好避免会影响此功能的动作,包括提交表单时禁用表单控件或让页面内容透明或不可见的渐出特效。

简单的解决方法是使用 onunload 监听器 reset 渐出效果或重新 enable 表单控件。注意对有些浏览器来说,如 Firefox 和 Safari,为 unload 事件添加监听器会禁用历史浏览。而在 Opera 中禁用提交按钮会导致禁用历史浏览。

复制代码 代码如下:

window.onunload = function () { document.body.style.opacity = '1'; };

使用 XMLHttpRequest

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

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