高性能JavaScript笔记之数据存取 (上)

四种基本的数据存储位置

数据的存储位置会很大程度上影响其读取速度。JavaScript 有四种基本的数据存储的位置:

  • 字面量。字面量只代表自身,不存储在特定位置。JavaScript 中的字面量有:字符串、数字、布尔值、对象、数组、函数、正则表达式,以及特殊的 null 和 undefined 值。
  • 本地变量。开发人员使用关键字 var 定义的数据存储单元。
  • 数组元素。存储在 JavaScript 数组对象内部,以数字做为索引。
  • 对象成员。存储在 JavaScript· 对象内部,以字符串作为索引。

存取消耗的时间比较:

字面量 ≈ 本地变量 < 数组元素 ≈ 对象成员

建议:如果在乎运行速度,那么尽量使用字面量和局部变量,减少数组项和对象成员的使用。

管理作用域

作用域链和标识符解析

执行函数时会创建一个称为执行环境(execution context)的内部对象。一个执行环境定义了一个函数执行时的环境。函数每次执行时对应的执行环境都是独一无二的,所以多次调用同一个函数就会导致创建多个执行环境。当函数执行完毕,执行环境就会被摧毁。

在函数执行过程中,每遇到一个变量,都会经历一次标识符解析过程以及决定从哪里获取或存储数据。该过程搜索执行环境的作用域链,查找同名的标识符。搜索过程从作用域链头部开始,也就是当前运行函数的活动对象。如果没找到,则继续搜素作用域链中的下一个对象。正是这个搜索过程影响了性能。

标识符解析的性能

在执行环境中的作用域链中,一个标识符位置越深,它的读写速度就越慢。因此函数中读写局部变量总是最快的,而读写全局变量通常是最慢的,因为全局变量总是存在于执行环境作用域链的最末端。

建议:尽量使用局部变量。一个好的经验法则是:如果某个跨作用域的值在函数中被引用一次以上,那么就把它储存到局部变量里。

闭包性能问题

思考以下代码,尝试理解与闭包有关的性能问题:

function assignEvent() {
	var id = "xdi9592";

	document.getElementById("save-btn").onclick = function(event) {
		saveDocument(id);
	};
}

onclick 事件是一个闭包,它在 assignEvent() 执行时创建。
当 assignEvent() 函数执行时,一个包含变量 id以及其他数据的活动对象被创建。他成为执行环境作用域链中的第一个对象,而全局变量紧随其后。当闭包被创建时,它的[[scope]]属性被初始化为这些对象
在这里插入图片描述
由于闭包的[[scope]]属性包含了与执行环境作用域链相同的对象的引用,因此会产生副作用。通常来说,函数的活动对象会随着执行环境一同摧毁,但引入闭包后,由于引用闭包仍然存在闭包的[[scope]]属性中,因此激活对象无法被摧毁。这意味着脚本中的闭包与非闭包函数相比,需要更多的内存开销。

当闭包代码被执行时,会创建一个执行环境,它的作用域链与属性[[scope]]中所引用的两个相同的作用域链对象一起被初始化,然后一个活动对象为闭包自身对象所创建。
在这里插入图片描述
注意闭包中用到的两个标识符,id 和 saveDocument,它们的位置在作用域链的第一个对象之后。这就是使用闭包最需要关注的性能点:在频繁访问跨作用域的标识符时,每次访问都会带来性能损失。

建议:将常用的跨作用域变量存储在局部变量中,然后直接访问局部变量。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值