0

0

javascript性能优化的方法介绍(附示例)

不言

不言

发布时间:2018-11-17 15:03:41

|

2753人浏览过

|

来源于segmentfault

转载

本篇文章给大家带来的内容是关于javascript性能优化的方法介绍(附示例),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。

本文主要是在我读《高性能Javascript》之后,想要记录下一些有用的优化方案,并且就我本身的一些经验,来大家一起分享下,

Javascript的加载与执行

大家都知道,浏览器在解析DOM树的时候,当解析到script标签的时候,会阻塞其他的所有任务,直到该js文件下载、解析执行完成后,才会继续往下执行。因此,这个时候浏览器就会被阻塞在这里,如果将script标签放在head里的话,那么在该js文件加载执行前,用户只能看到空白的页面,这样的用户体验肯定是特别烂。对此,常用的方法有以下:

立即学习Java免费学习笔记(深入)”;

  • 将所有的script标签都放到body最底部,这样可以保证js文件是最后加载并执行的,可以先将页面展现给用户。但是,你首先得清楚,页面的首屏渲染是否依赖于你的部分js文件,如果是的话,则需要将这一部分js文件放到head上。

  • 使用defer,比如下面这种写法。使用defer这种写法时,虽然浏览器解析到该标签的时候,也会下载对应的js文件,不过它并不会马上执行,而是会等到DOM解析完后(DomContentLoader之前)才会执行这些js文件。因此,就不会阻塞到浏览器。

  • 动态加载js文件,通过这种方式,可以在页面加载完成后,再去加载所需要的代码,也可以通过这种方式实现js文件懒加载/按需加载,比如现在比较常见的,就是webpack结合vue-router/react-router实现按需加载,只有访问到具体路由的时候,才加载相应的代码。具体的方法如下:

1.动态的插入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('加载完成');
  })

2.通过xhr方式加载js文件,不过通过这种方式的话,就可能会面临着跨域的问题。例子如下:

  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);
      }
    }
  }

3.将多个js文件合并为同一个,并且进行压缩。 原因:目前浏览器大多已经支持并行下载js文件了,但是并发下载还是有一定的数量限制了(基于浏览器,一部分浏览器只能下载4个),并且,每一个js文件都需要建立一次额外的http连接,加载4个25KB的文件比起加载一个100KB的文件消耗的时间要大。因此,我们最好就是将多个js文件合并为同一个,并且进行代码压缩。

汕头吧网上商城系统
汕头吧网上商城系统

特点与优点:1.界面布局合理美观,浏览方便,更具商城站点的风格;2.前后台功能强大好用,如三级分类、竞拍、排行榜、特价、促销、积分等;3.更具人性化,如定单反馈、会员与VIP分别显示不同的售价等;4.优化程序代码,执行速度快速;5.不错的短信联络管理员以及留言本的悄悄话功能等。功能介绍:商品的添加、修改、删除。 管理商品的订单及修改订单状态和网友对商品的评论。管理网站前台用户,可进行修改、删除操作

下载

javascript作用域

当一个函数执行的时候,会生成一个执行上下文,这个执行上下文定义了函数执行时的环境。当函数执行完毕后,这个执行上下文就会被销毁。因此,多次调用同一个函数会导致创建多个执行上下文。每隔执行上下文都有自己的作用域链。相信大家应该早就知道了作用域这个东西,对于一个函数而言,其第一个作用域就是它函数内部的变量。在函数执行过程中,每遇到一个变量,都会搜索函数的作用域链找到第一个匹配的变量,首先查找函数内部的变量,之后再沿着作用域链逐层寻找。因此,若我们要访问最外层的变量(全局变量),则相比直接访问内部的变量而言,会带来比较大的性能损耗。因此,我们可以将经常使用的全局变量引用储存在一个局部变量里

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;
  }

DOM操作优化

  • 最小化DOM的操作次数,尽可能的用javascript来处理,并且尽可能的使用局部变量储存DOM节点。比如以下的代码:

  // 优化前,在每次循环的时候,都要获取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;
  }
  • 尽可能的减少重排和重绘,重排和重汇可能会代价非常昂贵,因此,为了减少重排重汇的发生次数,我们可以做以下的优化

1.当我们要对Dom的样式进行修改的时候,我们应该尽可能的合并所有的修改并且一次处理,减少重排和重汇的次数。

  // 优化前
  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;'

2.当我们要批量修改DOM节点的时候,我们可以将DOM节点隐藏掉,然后进行一系列的修改操作,之后再将其设置为可见,这样就可以最多只进行两次重排。具体的方法如下:

  // 未优化前
  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);

3.使用事件委托:事件委托就是将目标节点的事件移到父节点来处理,由于浏览器冒泡的特点,当目标节点触发了该事件的时候,父节点也会触发该事件。因此,由父节点来负责监听和处理该事件。

那么,它的优点在哪里呢?假设你有一个列表,里面每一个列表项都需要绑定相同的事件,而这个列表可能会频繁的插入和删除。如果按照平常的方法,你只能给每一个列表项都绑定一个事件处理器,并且,每当插入新的列表项的时候,你也需要为新的列表项注册新的事件处理器。这样的话,如果列表项很大的话,就会导致有特别多的事件处理器,造成极大的性能问题。而通过事件委托,我们只需要在列表项的父节点监听这个事件,由它来统一处理就可以了。这样,对于新增的列表项也不需要做额外的处理。而且事件委托的用法其实也很简单:

function handleClick(target) {
  // 点击列表项的处理事件
}
function delegate (e) {
  // 判断目标对象是否为列表项
  if (e.target.nodeName === 'LI') {
    handleClick(e.target);
  }
}
const parent = document.getElementById('parent');
parent.addEventListener('click', delegate);


相关文章

数码产品性能查询
数码产品性能查询

该软件包括了市面上所有手机CPU,手机跑分情况,电脑CPU,电脑产品信息等等,方便需要大家查阅数码产品最新情况,了解产品特性,能够进行对比选择最具性价比的商品。

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
全局变量怎么定义
全局变量怎么定义

本专题整合了全局变量相关内容,阅读专题下面的文章了解更多详细内容。

78

2025.09.18

python 全局变量
python 全局变量

本专题整合了python中全局变量定义相关教程,阅读专题下面的文章了解更多详细内容。

96

2025.09.18

js正则表达式
js正则表达式

php中文网为大家提供各种js正则表达式语法大全以及各种js正则表达式使用的方法,还有更多js正则表达式的相关文章、相关下载、相关课程,供大家免费下载体验。

512

2023.06.20

js获取当前时间
js获取当前时间

JS全称JavaScript,是一种具有函数优先的轻量级,解释型或即时编译型的编程语言;它是一种属于网络的高级脚本语言,主要用于Web,常用来为网页添加各式各样的动态功能。js怎么获取当前时间呢?php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

244

2023.07.28

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

298

2023.08.03

js是什么意思
js是什么意思

JS是JavaScript的缩写,它是一种广泛应用于网页开发的脚本语言。JavaScript是一种解释性的、基于对象和事件驱动的编程语言,通常用于为网页增加交互性和动态性。它可以在网页上实现复杂的功能和效果,如表单验证、页面元素操作、动画效果、数据交互等。

5306

2023.08.17

js删除节点的方法
js删除节点的方法

js删除节点的方法有:1、removeChild()方法,用于从父节点中移除指定的子节点,它需要两个参数,第一个参数是要删除的子节点,第二个参数是父节点;2、parentNode.removeChild()方法,可以直接通过父节点调用来删除子节点;3、remove()方法,可以直接删除节点,而无需指定父节点;4、innerHTML属性,用于删除节点的内容。

481

2023.09.01

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

212

2023.09.04

Python 自然语言处理(NLP)基础与实战
Python 自然语言处理(NLP)基础与实战

本专题系统讲解 Python 在自然语言处理(NLP)领域的基础方法与实战应用,涵盖文本预处理(分词、去停用词)、词性标注、命名实体识别、关键词提取、情感分析,以及常用 NLP 库(NLTK、spaCy)的核心用法。通过真实文本案例,帮助学习者掌握 使用 Python 进行文本分析与语言数据处理的完整流程,适用于内容分析、舆情监测与智能文本应用场景。

10

2026.01.27

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PostgreSQL 教程
PostgreSQL 教程

共48课时 | 7.9万人学习

Django 教程
Django 教程

共28课时 | 3.6万人学习

SciPy 教程
SciPy 教程

共10课时 | 1.3万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号