数据存取与DOM编程
数据存取
一般数据的存储位置是很影响性能的,但是 JS 的问题相对简单,因为可选方案比较少。但是存储位置很大程度影响读取速度。
- 字面量:只代表本身,不存储在特定位置,比如字符串,数字,布尔,对象,数组,函数,正则等,null,undefined。
- 本地变量:使用 var 定义的存储单元
- 数组元素:存在数组对象内部,数字作为索引
- 对象成员:存在 js 对象内部,字符串作为索引
一般字面量和本地变量的存取性能基本可以忽略,数组元素和对象成员的稍微高一些。具体的实现也是看浏览器的,比如 FF 对于数组的性能进行了优化,也会很快,但是一般对象成员的损耗是最高的。
管理作用域
作用域很重要,不只是性能,还有功能的角度。
作用域链和标识符解析
JS 函数是一个对象,是 Function 对象的实例。
与其他对象一样,既拥有可以编程访问的属性,还有一系列仅供JS引擎存取的内部属性
,比如[[scope]]。
[[scope]]包含了一个函数被创建的作用域中对象的集合,这个集合被称之为函数的作用域链。如果是一个全局对象,那么作用域链就会插入一个指向全局对象的一个指针,可以访问到全局中的所有对象。
执行函数时会创建一个执行环境,每次执行函数都会创建执行环境。
每个执行环境都有自己的作用域链,当执行时,他的作用域链初始化为[[scope]]的作用域链,然后创建一个包含了所有局部变量(包括参数,this)的”活动对象”,添加到作用域链的最顶层。当执行完成,执行环境被销毁,活动对象也随之销毁。
每次进行变量的查找时,都会从执行环境作用域链的顶部(活动对象)开始查找,正是这个搜索的过程影响了性能。
标识符解析的性能
很明显,变量埋得越深,查找越需要消耗性能。
解决方法也比较简单,就是跨作用域的值如果访问了多次的话,就用一个局部变量存储起来
。
改变作用域链
with 语句 与 try–catch 语句
with 是可以延长作用域链的,就是说使用了 with 之后,这个对象的所有属性放入一个变量对象,然后放置到了作用域链的顶部。
try…catch 语句的 catch 也是可以延长作用域链,异常对象会被放入变量对象,然后放到作用域的顶部
注意这里是临时被改变的,catch 或者 with 语句一旦执行结束,作用域链就会变回原来的状态。
我们可以把 catch 语句里面的错误委托给一个函数来处理。由于只执行了一条语句,而且没有局部变量访问,作用域的临时改变就不会影响代码性能。
动态作用域
with,try–catch,和 eval 都是动态的作用域,有些浏览器的优化是没法支持动态作用域的。
闭包,作用域和内存
闭包是外部函数被执行的时候创建的。
外部函数被执行时,他会创建自己的活动对象,然后加到自己的作用域链中。闭包会被创建,作用域链初始化为外部函数的活动对象以及全局对象。然后闭包被执行的时候,又会往自己的作用域链中推入自己的活动对象。
一般情况下,函数执行完成,执行环境与活动对象就会被销毁,这里由于闭包仍然拥有外部函数活动对象的引用,所以暂时无法回收。注意 IE 由于使用非原生 Js 对象来实现 DOM,因此会导致内存泄漏(勐喆说 IE 不能搞定循环依赖)(说是 DOM 对象被回收了,JS 对象可能没法回收,导致内存的泄露)
比如:
function a() {
function b() {}
return b;
}
//到这里啥都不执行,a的作用域链为全局,b还未被创建
var c = a(); //执行过程中a的作用域链为a的活动对象+全局,c即为b,作用域链为a的活动对象+全局。执行完a的执行环境销毁,但是a的活动对象还存在,因为c引用着。
c(); //这样子执行,c的作用域链为c的活动对象+a的活动对象+全局;执行完了,执行环境被销毁,c的作用域链为a的活动对象+全局,所以a的活动对象就不会被回收
//除非脚本执行完了,或者手动设置为null,或者简单地用个自定义匿名函数包起来。
a()(); //这样子执行,执行完了所有的活动对象,作用域就被销毁了
所以闭包的内存问题其实是由于不正确的使用导致的。但是我们用个匿名函数包起来也能够结果,就怕那种循环嵌套的,会导致内存可能会泄露。
原型链与嵌套成员
原型链的访问同理,需要遍历原型链,所以埋得越深当然性能会消耗的越多
嵌套成员一样,window.location.href 肯定是比 location.href 慢的
就是尽量避免读取同一个对象属性,用局部变量来保存一下。
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 981909093@qq.com
文章标题:数据存取与DOM编程
文章字数:1.4k
本文作者:泽鹿
发布时间:2019-08-28, 16:45:23
最后更新:2019-08-28, 16:45:23
原始链接:http://panyifei.github.io/2019/08/28/读书笔记/高性能Javascript/2章数据存取/版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。