标签:行修改 插入 支持 原因 浏览器 执行 nod 多个 最快
本文主要是在我读《高性能Javascript》之后,想要记录下一些有用的优化方案,并且就我本身的一些经验,来大家一起分享下,
大家都知道,浏览器在解析DOM树的时候,当解析到script标签的时候,会阻塞其他的所有任务,直到该js文件下载、解析执行完成后,才会继续往下执行。因此,这个时候浏览器就会被阻塞在这里,如果将script标签放在head里的话,那么在该js文件加载执行前,用户只能看到空白的页面,这样的用户体验肯定是特别烂。对此,常用的方法有以下:
<script src="test.js" type="text/javascript" defer></script>
function loadScript(url, callback) {
const script = document.createElement(‘script‘);
script.type = ‘text/javascript‘;
// 处理IE
if (script.readyState) {
script.onreadystatechange = function () {
if (script.readyState === ‘loaded‘ || script.readyState === ‘complete‘) {
script.onreadystatechange = null;
callback();
}
}
} else {
// 处理其他浏览器的情况
script.onload = function () {
callback();
}
}
script.src = url;
document.body.append(script);
}
// 动态加载js
loadScript(‘file.js‘, function () {
console.log(‘加载完成‘);
})
const xhr = new XMLHttpRequest();
xhr.open(‘get‘, ‘file.js‘);
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status < 300 || xhr.status === 304>) {
const script = document.createElement(‘script‘);
script.type = ‘text/javascript‘;
script.text = xhr.responseText;
document.body.append(script);
}
}
}
当一个函数执行的时候,会生成一个执行上下文,这个执行上下文定义了函数执行时的环境。当函数执行完毕后,这个执行上下文就会被销毁。因此,多次调用同一个函数会导致创建多个执行上下文。每隔执行上下文都有自己的作用域链。相信大家应该早就知道了作用域这个东西,对于一个函数而言,其第一个作用域就是它函数内部的变量。在函数执行过程中,每遇到一个变量,都会搜索函数的作用域链找到第一个匹配的变量,首先查找函数内部的变量,之后再沿着作用域链逐层寻找。因此,若我们要访问最外层的变量(全局变量),则相比直接访问内部的变量而言,会带来比较大的性能损耗。因此,我们可以将经常使用的全局变量引用储存在一个局部变量里。
const a = 5;
function outter () {
const a = 2;
function inner () {
const b = 2;
console.log(b); // 2
console.log(a); // 2
}
inner();
}
javascript中,主要分为字面量、局部变量、数组元素和对象这四种。访问字面量和局部变量的速度最快,而访问数组元素和对象成员相对较慢。而访问对象成员的时候,就和作用域链一样,是在原型链(prototype)上进行查找。因此,若查找的成员在原型链位置太深,则访问速度越慢。因此,我们应该尽可能的减少对象成员的查找次数和嵌套深度。比如以下代码
// 进行两次对象成员查找
function hasEitherClass(element, className1, className2) {
return element.className === className1 || element.className === className2;
}
// 优化,如果该变量不会改变,则可以使用局部变量保存查找的内容
function hasEitherClass(element, className1, className2) {
const currentClassName = element.className;
return currentClassName === className1 || currentClassName === className2;
}
// 优化前,在每次循环的时候,都要获取id为t的节点,并且设置它的innerHTML
function innerHTMLLoop () {
for (let count = 0; count < 15000; count++) {
document.getElementById(‘t‘).innerHTML += ‘a‘;
}
}
// 优化后,
function innerHTMLLoop () {
const tNode = document.getElemenById(‘t‘);
const insertHtml = ‘‘;
for (let count = 0; count < 15000; count++) {
insertHtml += ‘a‘;
}
tNode.innerHtml += insertHtml;
}
// 优化前
const el = document.getElementById(‘test‘);
el.style.borderLeft = ‘1px‘;
el.style.borderRight = ‘2px‘;
el.style.padding = ‘5px‘;
// 优化后,一次性修改样式,这样可以将三次重排减少到一次重排
const el = document.getElementById(‘test‘);
el.style.cssText += ‘; border-left: 1px ;border-right: 2px; padding: 5px;‘
// 未优化前
const ele = document.getElementById(‘test‘);
// 一系列dom修改操作
// 优化方案一,将要修改的节点设置为不显示,之后对它进行修改,修改完成后再显示该节点,从而只需要两次重排
const ele = document.getElementById(‘test‘);
ele.style.display = ‘none‘;
// 一系列dom修改操作
ele.style.display = ‘block‘;
// 优化方案二,首先创建一个文档片段(documentFragment),然后对该片段进行修改,之后将文档片段插入到文档中,只有最后将文档片段插入文档的时候会引起重排,因此只会触发一次重排。。
const fragment = document.createDocumentFragment();
const ele = document.getElementById(‘test‘);
// 一系列dom修改操作
ele.appendChild(fragment);
function handleClick(target) {
// 点击列表项的处理事件
}
function delegate (e) {
// 判断目标对象是否为列表项
if (e.target.nodeName === ‘LI‘) {
handleClick(e.target);
}
}
const parent = document.getElementById(‘parent‘);
parent.addEventListener(‘click‘, delegate);
标签:行修改 插入 支持 原因 浏览器 执行 nod 多个 最快
原文地址:https://www.cnblogs.com/chenjg/p/8782165.html