这本书是2010年出版的,这本书谈性能是有时效性的,如今立刻就2018年了,这几年前端发展的速度是飞快的,书里面还有一些内容考虑IE六、七、8的东西,却不知如今这些都已经再也不考虑了,因此不可避免的有一些知识是比较老的。有些解决方法如今已经不是最好的解决方式,好比工具那一章。css
总的来讲,这本书总体给出的性能优化建议,以及做者耐心的实践,对咱们开发优化的启发和帮助仍是很大的,由于它里边的不少知识,都是做者经过实践总结出来的,都是经验的积累,这在通常的教科书上是学不到的。特别是对于js基础比较差一点的,里面有不少知识点尽管在如今仍是很是有必要的。html
下面我就将各章节的一些重要的知识点总结写出来,争取将干货都提取出来。前端
本文首发于个人我的blog:obkoro1.comwebpack
当浏览器在执行js代码的时候,不能同时作其余事情。(界面ui线程和js线程用的是同一进程,因此js执行越久,网页的响应时间越长。)nginx
若是把脚本<script>
放在<head>
中,页面会等js文件所有下载并执行完成后才开始渲染,在这些文件下载和执行的过程当中:会致使访问网站的时候有明显的延迟,表现为:页面空白。es6
性能提高:推荐将全部的<script>
标签尽量的放到<body>
标签的底部,优先渲染页面,减小页面空白时间。web
每一个<script>
标签初始下载的时候都会阻塞页面的渲染。性能提高作法: 减小内嵌脚本:减小内嵌的<script>
标签,将代码写在一个标签中。ajax
合并外链的js文件:http请求会带来额外的性能开销,栗子:下载一个100KB的js文件比下载4个25kb的js文件更快。具体操做方法自行搜索。正则表达式
script标签的aync属性:算法
async 属性规定一旦脚本可用,则会异步执行。async 属性仅适用于外部脚本(只有在使用 src 属性时)。若是 async="async":脚本相对于页面的其他部分异步地执行(当页面继续进行解析时,脚本将被执行)
script标签的defer属性:
js文件在页面解析到script标签的时候开始下载,但并不会执行,dom加载完成执行。这两个属性的区别在于执行时机。
动态脚本元素。
js操做dom建立<script>
标签,自定义生成标签的type、src属性。文件会在该元素被添加到页面的时候开始下载。ps:若是文件顺序很重要的话,最好按照顺序合成一个文件。而后再添加到页面中。这样:不管什么时候启动下载。文件的下载和执行过程不会阻塞页面的其余进程。
用get请求一个文件,请求好了。而后建立动态脚本,最后添加进去。 缺陷:文件要再请求页面的同一个域。不能从cdn下载
<script>
标签。性能:访问字面量和局部变量的速度是最快的,访问数组和对象成员相对较慢
搜索执行环境的做用域链,查找同名标识符。搜索过程从做用域链头部开始,也就是当前运行函数的活动对象。若是找到,就使用这个标识符,对应的变量;若是没有找到,继续搜索下面的对象。搜索过程会持续进行,直到找到标识符,若没法搜索到匹配的对象,那么标识符被视为未定义、
性能问题:一个标识符所在的位置越深,它的读写速度也就越慢。所以,函数中读写局部变量老是最快的,而读写全局变量一般是最慢的。
建议:将全局变量存储到局部变量,加快读写速度。
优化建议:将经常使用的跨做用域变量存储到局部变量,而后直接访问局部变量。理由如上,变量标识符解析过程。
for、while和do-while循环性能差很少,for-in循环速度只有前面几种类型的1/7,因此尽可能避免使用for-in循环,除非你须要遍历一个属性数量未知的对象。
forEach比for慢,若是运行速度要求严格,不建议使用。
改善循环性能的最佳方式是减小每次迭代的工做量和减小循环迭代的次数。
减小迭代工做量:减小属性查找和倒序循环,循环次数越多,性能优化越明显。
for(var i=0;i<items.length;i++){代码}//正序循环
for(var i=items.length;i--){代码}//倒序循环
//减小属性查找:查找一次属性,把值存在局部变量,在控制条件里面使用这个变量
倒序循环在i>0的时候会自动转换为true,等于0的时候为false。
//倒序循环:控制条件从(迭代数少于总数吗?它是否为true?)变为(它是否为true)
复制代码
减小迭代的次数:"Duff's Device"循环体展开技术,有兴趣的能够看一下,迭代工做量大于1000的时候适用。
if-else与switch:条件数量越大,越倾向于使用switch。
优化if-else:
一、把最可能出现的条件放在首位。二、使用二分法把值域分红一系列的区间。
复制代码
浏览器的调用栈大小限制了递归算法在js中的应用;栈溢出错误会致使其余代码中断运行。
当心使用递归,如今es6递归能够尾递归,在es6中只要使用尾递归就不会发生栈溢出,相对节省性能。
复制代码
字符串合并的时候使用简单的'+'和'+='操做符。
str+='abc'+'efg;//2个以上的字符串拼接,会产生临时字符串
str=str+'abc'+'efg';//推荐,提速10%~40%
复制代码
书里面讲的正则原理和回溯原理,这个很重要,找个篇博客:跟书里面讲的差很少,但仍是建议你们能够去找找PDF好好看看正则表达式这节。
提升正则表达式效率的方法:
一、最重要的是:具体化正则表达式!具体化正则表达式!具体化正则表达式!
二、关注如何让匹配更快失败,找出一些必需,特殊的字符
三、正则表达式以简单的、必需的字元开始。
四、使用量词模式,使它们后面的字元互斥。
五、较少分支数量,缩小分支范围
六、使用合适的量词
七、把正则表达式赋值给变量并重用
八、将复杂的正则拆分为简单的片断
//事实上,书里面讲的方法不止这么几个,并且每个都有详细的解析 大佬们 仍是去看看这一章节吧
复制代码
正则表达式并不老是最好的解决方案,当你只是搜索字面字符串或者你事先知道字符串的哪一部分将要被查找时:
使用indexOf()和lastIndexOf()更适合查找特定字符串的位置或者判断它们是否存在
//例如:判断当前浏览器之类。
复制代码
js和用户界面更新在同一个进程中运行,所以一次只能处理一件事情。高效的管理UI线程就是要确保js不能运行太长时间,以避免影响用户体验。
浏览器限制了js任务的运行时间,这种限制颇有必要,它确保某些恶意代码不能经过永不中止的密集操做锁住用户的浏览器。此限制分为两种:调用栈的大小和长时间运行脚本。
任何js任务都不该当执行超过100毫秒。过长的运行时间会致使UI更新出现明显延迟,从而对用户体验形成负面影响。
定时器可用来安排代码延迟执行,它使得你能够把长时间运行脚本分解成一系列的小任务。
这一章节貌似东西都比较老一点。。
post更适合发送大量数据到服务器。
get请求可以被浏览器缓存,Expires头信息设置浏览器缓存请求多久。可用于从不改变的图片或者其余静态数据集(js、css等)
JSON是一种使用js对象和数组直接量编写的轻量级且易于解析的数据格式,它不只传输尺寸小,并且解析速度快。JSON是高性能AJAX的基础,尤为在使用动态脚本注入时。
json应该是近几年一直在用的。。。
避免双重求值:避免使用eval()和 function()构造器来避免双重求值带来的性能消耗,一样的,给setTimeout()和setInterval()传递函数而不是字符串做为参数。
//双重求值:就是在js代码中执行另外一段js代码,不建议使用下面这些方式
eval('代码')
function构造函数--new function('代码')
setTimeout(‘代码’,100)和setInterval(‘代码’,100)
复制代码
尽可能使用直接量建立对象和数组。直接量的建立和初始化都比非直接量形式要快。
避免作重复工做,能节省的步骤就节省。
js原生方法总会比你写的任何代码都要快。
构建和部署的过程对基于js的web应用的性能有着巨大影响。这个过程当中最重要的步骤有:
这些都是在构建过程当中完成的工做,不要等到运行时去作,webpack也是在构建过程当中,完成的工做。 2. 经过正确设置HTTP响应头来缓存js文件,经过向文件名增长时间戳来避免缓存问题。 3. 使用CDN提供js文件;CDN不只能够提高性能,它也为你管理文件的压缩与缓存,。
当网页变慢时,分析从网络下载的资源以及分析的资源以及分析脚本的运行性能能让你专一于那些最须要优化的地方。
使用网络分析工具找出加载脚本和页面中其余资源的瓶颈,这会帮助你决定那些脚本须要延迟加载,或者须要进一步分析。
检查图片、样式表和脚本的加载过程,以及它们对页面总体加载和渲染的影响。从而针对性的作出优化
复制代码
把脚本尽量延迟加载,这样作能够加快页面渲染速度,给用户带来更好的体验。
确认脚本和其余资源文件的加载过程已经被优化
这里主要是说文件从服务器的下载速度,好比服务器那边的配置问题之类的。
栗子:我就被后端坑过。一个js文件就200k ,下载下来须要50秒钟!
后面发现原来是后端那边nginx没有开启加速配置什么的,致使出现的问题,找问题找半天。
复制代码
测试脚本的运行时间,用一个Date实例减去另外一个Date实例,获得的时间差就是脚本运行消耗的时间。
let start=new Date();
//你的代码
let time=newDate()-start;
复制代码
chrome ,火狐 等主流浏览器的控制面板,已经可以反映不少性能问题。仔细分析就能找出不少问题。例如:资源加载,断点等
事实上,自认为这本书最宝贵的就是一些提到的细节,好比:
一、字符串合并的时候使用简单的'+'和'+='操做符。
str+='abc'+'efg;//2个以上的字符串拼接,会产生临时字符串
str=str+'abc'+'efg';//推荐,提速10%~40%
复制代码
二、避免双重求值:避免使用eval()和 function()构造器来避免双重求值带来的性能消耗,一样的,给setTimeout()和setInterval()传递函数而不是字符串做为参数。
//双重求值:就是在js代码中执行另外一段js代码,不建议使用下面这些方式
eval('代码')
function构造函数--new function('代码')
setTimeout(‘代码’,100)和setInterval(‘代码’,100)
复制代码
书不太厚,若是对里面的内容感兴趣,仍是建议买一本回家看一看。
以上2018.1.9