JavaScript中有四种基本的数据存取位置:

  • 直接量

直接量只代表自身,不存储在特定位置。JS中的直接量有:字符串,数字,布尔值,对象,数组,函数,正则表达式,以及特殊的null和undefined值。

  • 变量

用var定义的数据存储单元

  • 数组元素

存储在JS数组对象内部,以数字作为索引

  • 数据成员

存储在JS对象内部,以字符串为索引

作用域工作原理和标识符解析

关键字:内部属性[[Scope]]、可变对象、运行期上下文、执行环境、活动对象

1. 作用域工作原理

作用域链的作用:存储执行环境可以访问的数据,使用方法是标识符解析

每一个JS函数都表示为一个对象,更确切的说,是Function对象的一个实例。Function对象同其他对象一样,拥有可以编程访问的属性,和一系列不能通过代码访问而仅供JS引擎存取的内部属性。内部属性[[Scope]]指向一个函数被创建的作用域中对象的集合。这个集合被称为函数的作用域链,它决定哪些数据可以被函数访问。函数作用域中的每个对象被称为可变对象,每个可变对象都以“键值对”的形式存在。当一个函数被创建后,它的作用域链会被创建此函数的作用域中可访问的数据对象所填充。思考下面的全局函数

function add(num1, num2) {

var sum = num1 + num2;

return sum;

}

当函数add()创建时,它的作用域链填入了一个单独的可变对象,包含了函数能访问到的所有数据。本可变对象是时刻存在的全局对象。

函数add的作用域将会在执行时用到。

var total = add(1, 2);

执行此函数时会创建一个称为”运行期上下文”的内部对象。一个运行期上下文定义了一个函数的执行环境。函数每次执行时对应的运行期上下文都是独一无二的,所以多次调用同一函数就会导致创建多个运行期上下文。当函数执行完毕,执行期上下文会被销毁。

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

2. 标识符解析过程

在函数执行过程中,每遇到一个变量,都会经历一次标识符解析过程以决定从哪里获取或存储数据。该过程搜索运行期上下文的作用域链,查找同名的标识符。搜索过程从作用域链头部开始,也就是当前运行函数的活动对象。如果找到了,就使用这个标识符对应的变量;如果没找到,继续搜索作用域链中的下一个对象。搜索过程会持续进行,直到标识符被找到,或者没有可用于搜索的对象为止,这种情况下标识符被认为是未定义的。函数执行过程中,每个标识符都要经历这样的搜索过程。

对于所有浏览器而言,总的趋势是,一个标识符所在的位置越深(作用域链末端),它的读写速度也就越慢。一个好的经验法则是:如果某个跨作用域值在函数中被引用一次以上,那么就把它存储在局部变量里。

闭包,作用域和内存

官方解释为: 所谓“闭包”,指的是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分。
我认为闭包就是能够读/写函数内部的某些变量的子函数,并将这些变量保存在内存中.

function assignEvents() {

var id = ‘index’;

document.getElementById(“save-btn”).onclick = function(event) {

saveDocument(id);

};

}

函数给一个DOM元素设置事件处理器。这个事件处理器就是一个闭包,它在函数执行时被创建,并且能访问所属作用域的id变量。为了让这个闭包访问id变量,必须创建一个特别的作用域链。

当assignEvents()函数被执行时,一个包含变量id的以及其他一些数据的活动对象被创建。它成为运行期上下文作用域链中第一个对象,而全局对象紧随其后。当闭包被创建时,它的[[Scope]]属性被初始化为这些对象。(如图)

因为闭包的[[Scope]]属性包含了与运行期上下文作用域相同的对象的引用,因此会有一些副作用。

通常的活动对象会随同运行期上下文一同销毁。但引入闭包时,由于引用仍然存在闭包的[[Scope]]属性中,因此活动对象无法被销毁。这意味着闭包的存在,需要更多的内存开销。

当闭包被执行时,一个运行期上下文被创建,它的作用域链与属性[[Scope]]中引用的两个相同的作用域链对象同时被初始化,然后一个活动对象为闭包自身所创建。

注意在闭包中用到的两个标识符,id和saveDocument,它们存在作用域链第一个对象之后的位置。这就是使用闭包最主要的性能关注点:要经常访问大量跨作用域的标识符,每次访问都会导致性能损失。

闭包的应用环境

1. 保护函数内的变量安全

2. 在内存中维持一个变量

对象成员

访问对象成员的速度比访问直接量或变量更慢,在某些浏览器中比访问数组元素还要慢。

JS中的对象是基于原型的。原型是其他对象的基础,定义并实现了一个新对象必须包含的成员列表。这一概念完全不同于传统面向对象编程语言的‘类’的概念,‘类’定义了创建新对象的过程。而原型对象为所有对象实例所共享,因此这些实例也共享了原型对象的成员。

实例通过一个内部属性绑定它的原型__proto__,比如一旦你创建一个内置对象(Object、Array)的实例,它们就会自动拥有一个Object实例作为原型。

实例可以有两种成员类型:

实例成员(也称‘own’成员):存在对象实例中

原型成员:由对象原型继承而来。

var Book = {

title: “JavaScript”,

content: ‘JavaScript是一门博大精深的语言’

};

alert(BooK.toString());              //[object Object]

方法toString()是对象Book继承而来的原型成员。解析对象成员的过程同解析变量十分相似。当Book.toString()

被调用时,会从对象实例开始,搜索名为’toString’成员。如果实例中不存在,那么会继续搜索其原型对象,直到

toString()方法被找到并且执行。实例可以访问它原型中的每一个属性和方法。

hasOwnProperty()判断对象是否包含特定的实例成员。

in操作符判断对象是否包含特定的属性。

原型链

对象的原型决定了实例的类型。默认情况下,所有对象都是Object的实例,并继承了所有基本方法。

嵌套成员

window.localhost.href每次遇到点操作符,嵌套成员会导致JavaScript引擎搜索所有对象成员。这些属性不是对象的实例属性,那么成员解析还需要搜索原型链,这会花更多的时间。

缓存对象成员值,不适合缓存对象的方法。

小结:

  1. 访问直接量和局部变量速度最快,相反,访问数据元素和对象成员相对较慢。
  2. 由于局部变量存在于作用域的起始位置,因此访问它比访问跨作用域变量更快。变量在作用域链中的位置越深,访问时间就越长。全局变量的访问所需时间最长,因为它处于作用域链的最末端。
  3. 嵌套的对象成员会明显影响性能,尽量少用。
  4. 属性或方法在原型链中的位置越深,访问它的速度也越慢(和访问变量相似)。
  5. 通常来说,可以通过把常用的对象成员、数组元素、跨域变量保存在局部变量中来改善JS性能,因为局部变量访问速度更快。

摘自:高性能JavaScript

转载于:https://www.cnblogs.com/mackxu/archive/2012/12/02/2798744.html

JS的数据访问及优化访问速度相关推荐

  1. 【深度学习-数据加载优化-训练速度提升一倍】

    1,介绍 数据加载 深度学习的训练,简单的说就是将数据切分成batch,丢入模型中,并计算loss训练.其中比较重要的一环是数据打batch部分(数据加载部分). 训练时间优化: 深度学习训练往往需要 ...

  2. 对于元组的访问 的优化访问方式

    NAME,SEX,EMAIL = range(3) student = ('戴磊','男','1@qq.com') print(student[NAME])

  3. 大数据量高并发访问的数据库优化方法

    一.数据库结构的设计 如果不能设计一个合理的数据库模型,不仅会增加客户端和服务器段程序的编程和维护的难度,而且将会影响系统实际运行的性能.所以,在一个系统开始实施之前,完备的数据库模型的设计是必须的. ...

  4. wordpress优化访问速度-图标修改-去除工具栏-搜索排除文章等实测有效

    目录 优化访问速度 搜索结果排除特定 ID 的文章或页面 搜索结果排除某些分类的文章 wordpress的前端页面的工具栏头部去除 wordpress页面标签图标的修改 优化访问速度 ======== ...

  5. 面向程序员的数据库访问性能优化法则

    面向程序员的数据库访问性能优化法则 特别说明: 1.   本文只是面对数据库应用开发的程序员,不适合专业 DBA , DBA 在数据库性能优化方面需要了解更多的知识: 2.   本文许多示例及概念是基 ...

  6. 「数据库系列杂谈」数据库访问性能优化

    为什么要优化 系统的吞吐量瓶颈往往出现在数据库的访问速度上 随着应用程序的运行,数据库的中的数据会越来越多,处理时间会相应变慢 数据是存放在磁盘上的,读写速度无法和内存相比 一.数据库访问优化法则简介 ...

  7. 数据库访问性能优化法则

    特别说明: 1.  本文只是面对数据库应用开发的程序员,不适合专业DBA,DBA在数据库性能优化方面需要了解更多的知识: 2.  本文许多示例及概念是基于Oracle数据库描述,对于其它关系型数据库也 ...

  8. 【转】面向程序员的数据库访问性能优化法则

    特别说明: 1.  本文只是面对数据库应用开发的程序员,不适合专业DBA,DBA在数据库性能优化方面需要了解更多的知识: 2.  本文许多示例及概念是基于Oracle数据库描述,对于其它关系型数据库也 ...

  9. Oracle数据库访问性能优化

    一.百万级数据库优化方案 1.对查询进行优化,要尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引. 2.应尽量避免在 where 子句中对字段进行 null 值判断 ...

最新文章

  1. 简述java中的注释以及用法_怎样理解 Java 注解和运用注解编程?
  2. ucosii事件控制块------消息邮箱与消息队列
  3. 我的第一个Android程序
  4. MobileNet V2 复现
  5. Node.js的交互式解释器(REPL)
  6. Linux下mp3文件的乱码问题
  7. ASP.NET 2.0 学习笔记 1: session 与 script 应用
  8. [转] Java, 使用 Reactor 进行反应式编程
  9. 为什么整数在python中表示d_python中整数的缓存机制
  10. wordpress函数wp_http_validate_url畸形IP绕过验证SSRF漏洞
  11. java电商项目的项目描述_Java电商项目-6.实现门户首页数据展示_Redis数据缓存
  12. 【目标跟踪】基于matlab背景差分多目标捕捉【含Matlab源码 810期】
  13. live2d_一款电脑桌面跨平台开源免费live2D桌面宠物精灵
  14. 构建自己的Conficker
  15. 向全国推荐优秀古籍整理图书活动入选书目公示(zz)
  16. IEEE论文参考文献格式(bib)
  17. xlsx的python处理
  18. 麻省理工的服务器位置,美国麻省理工大学位置在哪里?
  19. 人生就像剥洋葱,当你片片剥开,已经满眼泪水| 花一天时间,老机器安装Windows 98
  20. 【云原生】第二篇--容器管理工具 Docker生态架构及部署

热门文章

  1. 自定义ListView【通用】适配器并实现监听控件
  2. MAC打开EXE文件的三大方法
  3. NanoPi NEO的Matrix库硬件编程
  4. 《spring揭秘》读书笔记三
  5. Python学习教程(Python学习路线):Python3之递归函数简单示例
  6. 用c#开发微信(1)服务号的服务器配置和企业号的回调模式 - url接入
  7. nginx日志中文变成类似\xE9\xA6\x96\xE9\xA1\xB5-\xE6\x8E\xA8\xE8\x8D\x90的东西,治本方案
  8. 3. std::string::size_type
  9. OpenCV Shi-Tomasi角点检测
  10. python调用nacos账号密码,Python脚本,使用私钥(如果可用)或用户名密码