摘要:下面我跟大家分享关于标识符查找方面的优化问题。这个变量对象会首先被放入作用域链中。执行上下文也有一个作用域链,这个作用域链就是用来进行变量查找的。当执行上下文创建时,它的作用域链会用函数的属性来初始化。
前面两篇文章介绍了Javascript文件在页面中位置以及异步加载问题对前端性能的影响。不过受限于单线程的原因,不管采用哪种方法,只要Javascript进行了耗时的工作,就都会引起页面的阻塞。所以在写代码的过程中应该注意一些会影响代码性能的问题,这样才能让我们的优化尽量做到极致。下面我跟大家分享关于标识符查找方面的优化问题。
每个函数都有一个[[Scope]]属性,指向函数的作用域链,作用域链由多个变量对象组成。这个作用域链在函数定义的时候被创建,在函数定义时,会创建一个变量对象,这个变量对象包括了函数包含块所能访问到的变量,其实就是函数包含块的执行上下文。这个变量对象会首先被放入作用域链中。
function add(num1,num2){ var sum = num1 + num2 ; return sum ; }
在函数执行的时候,会创建一个叫做执行上下文的对象,这个执行上下文会用来进行函数的变量查找。执行上下文也有一个作用域链,这个作用域链就是用来进行变量查找的。当执行上下文创建时,它的作用域链会用函数的[[Scope]]属性来初始化。创建完执行上下文之后,又会创建一个叫做活动对象的变量对象并且放入作用域链的头部。这个活动对象包括所有局部变量,函数参数,arguments和this。这也说明了一个问题,就是this的值是在运行的时候决定的,而不是定义的时候。
var sum = add(1,2) ;
每次进行变量查找时,我们都要遍历执行上下文的作用域链,直到找到为止或者返回undefined。在这个过程中,变量查找的深度就会对性能产生影响。变量查找得越深,性能就越低。
由于现代浏览器对于JS的执行已经进行了优化,所以经过我的测试发现,变量查找的优化对于性能的提升不会产生太大的影响。虽然这么说,但是关于变量查找的优化方法还是可以借鉴的。
对于正常的情况,函数执行上下文的作用域在函数执行的时候是不会发生变化的,但是有几个特例情况会使作用域发生变化,这种现象叫做动态作用域。
withwith语句用来在特定作用域中引入变量对象,比如下面这段代码:
function test(){ with(document){ var link = getElementsByTagName("a") ; } }
通过with语句,在with作用域内的代码都可以直接访问document中的属性和方法。这个方法虽然可以方便得访问属性,但是也带来了一些副作用。在使用with语句时,会向函数执行上下文的作用域链的头部插入一个变量对象,这个变量对象的值就是with中包含的对象,这就意味着原来在作用域中的变量对象都被往后移了一位,也就是说查找这些变量要遍历更深一层作用域链。所以我们应该尽量避免使用with语句,可以通过声明局部变量然后赋值为document的方式来取代with语句。
try catchtry catch语句跟with一样,也会产生同样的影响,只是这次插入到作用域链中的变量对象是catch括号中的对象,一般就是错误对象e。
evaleval函数的坏处我想大家都应该知道了,通过eval执行的代码会污染全局变量,进而也会拉长变量的查找深度。
对象属性查找 原型和原型链 每个对象都有一个指向原型prototype的属性__proto__,多个对象的继承就形成了原型链。下图是一个关于原型和原型链的图:
关于原型链的介绍网上已经有很多了,我这里就不做介绍了。Javascript中的继承是通过原型链实现的,这就会导致一个问题,就是经过多次继承之后,原型链会变得很长,然后对于对象属性的查找就需要遍历更长的原型链,而遍历的越深效率必然就会越低。这就是对象属性查找的时候需要优化的一个地方。
上图是一个book对象的原型继承图,很容易发现如果要访问title属性那么只要直接再book对象上查找就可以了,但是如果要访问toString方法的话,那么就需要遍历到原型链最深处,这样的话效率肯定更低。一个常用的优化的方法就是用局部变量来保存对象的属性,后面只要直接访问这个局部变量就可以了。这方法跟函数中变量查找是一个道理。
现代浏览器对于对象属性的查找同样进行了优化,所以通过测试性能方面也没有太大的差别。
上面所说的是Javascript代码优化方面常见的两个问题,虽然现代浏览器对它们都进行了优化,但是如果要适配一些比较老旧的浏览器的话,还是需要注意的。而且上面说到的优化策略也是一个很好的编程规范。
最后,安利下我的个人博客,欢迎访问: http://bin-playground.top文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/78157.html
摘要:优化策略跟上面的大同小异,就是用局部变量缓存集合以及集合的长度,我就不进行实际测试了。例如错误的做法使用修改来进行优化如果需要动态修改,那么就使用批量处理操作并且让元素脱离文档流,等操作结束后再放回文档流中。 上篇我介绍了Javascript标识符查找方面的优化,可以看出在这方面的优化给性能带来的提升并不明显,甚至可以说基本没有影响。但是,我今天要分享的是前端Javascript优化的...
摘要:除此以外,让元素脱离文档流也是一个很好的方法。因为元素一旦脱离文档流,它对其他元素的影响几乎为零,性能的损耗就能够有效局限于一个较小的范围。讲完重排与重绘,往元素上绑定事件也是引起性能问题的元凶。高性能这本书非常精致,内容也非常丰富。 showImg(https://segmentfault.com/img/bVJgbt?w=600&h=784); 入手《高性能JavaScript》一...
摘要:减少作用域链上的查找次数。尽量少用全局变量,尽量使用局部变量。全局变量如果不手动销毁,会一直存在,造成全局变量污染,可能很产生一些意想不到的错误,而局部变量运行完成后,就被会被回收使用代替大量的内联样式修改。性能优化还需要继续深入研究。 关于前端性能优化的讨论一直都很多,包罗的知识也很多,可以说性能优化只有更好,没有最好。前面我写了一篇关于css优化的总结文章,今天再从javascri...
摘要:减少作用域链上的查找次数。尽量少用全局变量,尽量使用局部变量。全局变量如果不手动销毁,会一直存在,造成全局变量污染,可能很产生一些意想不到的错误,而局部变量运行完成后,就被会被回收使用代替大量的内联样式修改。性能优化还需要继续深入研究。 关于前端性能优化的讨论一直都很多,包罗的知识也很多,可以说性能优化只有更好,没有最好。前面我写了一篇关于css优化的总结文章,今天再从javascri...
摘要:减少作用域链上的查找次数。尽量少用全局变量,尽量使用局部变量。全局变量如果不手动销毁,会一直存在,造成全局变量污染,可能很产生一些意想不到的错误,而局部变量运行完成后,就被会被回收使用代替大量的内联样式修改。性能优化还需要继续深入研究。 关于前端性能优化的讨论一直都很多,包罗的知识也很多,可以说性能优化只有更好,没有最好。前面我写了一篇关于css优化的总结文章,今天再从javascri...
阅读 3547·2021-11-23 09:51
阅读 2778·2021-11-23 09:51
阅读 638·2021-10-11 10:59
阅读 1648·2021-09-08 10:43
阅读 3203·2021-09-08 09:36
阅读 3269·2021-09-03 10:30
阅读 3269·2021-08-21 14:08
阅读 2173·2021-08-05 09:59