高性能JavaScript(二)数据存取之作用域链

数据存取

    JavaScript与其他编程语言相同,数据的存取位置会很大程度的影响其读取速度。JavaScript中有下面四种基本的数据存储位置。

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

一般来说,字面量和局部变量的访问速度快于数组项和对象成员的访问速度。

管理作用域

    作用域概念是理解JavaScript的关键所在,不仅仅从性能角度,还包括从功能的角度。作用域的影响,从确定哪些变量可以被函数访问,到确定this的赋值。

1. 作用域链

    每一个JavaScript函数都是Function对象的一个实例。Function对象同其他对象一样,拥有可以编程的属性,和一系列不能通过代码访问而仅供JavaScript引擎存取的内部属性,其中一个内部属性是[[ scope]]。
    内部属性[[ scope]]包含了一个函数被创建的作用域中对象的集合,这个集合被称为函数的作用域链。函数作用域中每个对象被称为一个可变对象,每个可变对象都以“键值对”的形式存在。

2. 执行环境(执行上下文)

    当个函数创建后,它的作用域链会被创建此函数的作用域中可访问的数据对象所填充。执行这个函数是会创建一个称为执行环境(执行上下文)的内部对象。函数每次执行时的对应的执行环境都是独一无二的,所以多次调用这个函数就会创建多个执行环境。当函数执行完毕,执行环境就会被摧毁。

3. 活动对象

    每个执行环境都有自己的作用域链,用于解析标识符。当执行环境被创建时,它的作用域初始化为当前运行函数的[[ scope]]属性的对象。这些值按照它们出现在函数中的顺序,被复制到执行环境的作用域中。这个过程一旦完成,一个被称为“活动对象”的新对象就为执行环境创建好了。
    活动对象作为函数运行时的变量对象,包含了所有的局部变量,命名参数,参数集合以及this。然后此活动对象被推到作用域的最前端。当执行环境被销毁,活动对象也随之销毁。

4. 标识符解析

    在函数的执行过程中,每遇到一次变量都会经历一次标识符解析过程,从而决定从哪里获取或存储数据。这个过程会搜索执行环境的作用域链,查找同名的标识符。这个搜索过程从作用域链头部开始,也就是当前运行函数的活动对象开始。如果无法搜索到匹配的对象,标识符会被视为未定义。正是这个搜索过程影响了性能, 当一个标识符在作用域链中的深度越深, 解析它所花费的时间也越长。
    通常解析局部变量所花费的时间最少, 而全局变量总是存在于作用域链的末端, 解析它的时间时最长的。

总结

    1.当一个函数被创建时,这个Function对象的实例其中的一个内部属性[[ scope]]会被创建此函数的作用域中可被访问的对象填充,以集合形式存在,这个集合就是此函数的作用域链。
    2.当函数被执行时,它会创建一个名为执行上下文的内部属性,在此属性中包含了一个新的作用域链,这个作用域链中的内容是当前运行函数中[[ scope]]属性中的对象复制过来的,复制完成后一个新对象“活动对象”也创建完了。
    3.“活动对象”通常处于作用域链头部,所以解析标识符时搜索活动对象中的对象花费的时间比搜索全局变量这个处于作用域链最末端中的对象的时间会少许多。当我们需要重复使用全局变量时,我们可以通过将全局变量的引用赋值给局部变量以减少标识符解析中的性能开销。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值