高性能javascript(记录二)
js中有四种基本的数据存取位置。分别是:字面量、本地变量、数组元素、对象成员。
字面量:只代表自身,不存储在特定位置。js的字面量有:字符串、数字、布尔值、对象、数组、函数、正则表达式、以及特殊的null和undefined。
本地变量:开发人员使用关键字var定义的数据存储单元。
数组元素:存储在js数组对象内部,以数字作为索引。
对象成员:存储在js对象内部,以字符串作为索引。
总体来说:字面量和本地变量的访问速度快于数组项和对象成员的访问速度。
管理作用域:
- 作用域链和标示符解析
作用域链:内部属性[[scope]]包含了一个函数被创建的作用域中对象的集合。
函数的作用域链决定了哪些数据能被函数访问。函数作用域中的每个对象被称为一个可变对象,每个可变对象都以“键值对”的形式存在。当一个函数创建后,它的作用域链会被创建此函数的作用域中可访问的数据对象所填充。
例:function add(num1,num2){
var sum = num1+num2;return sum;
}
当函数add()创建时,它的作用域链中插入了一个对象变量,这个全局对象代表着所有在全局范围内定义的变量。

函数add()的作用域将会在执行时用到。假设执行:var total = add(5,10); 执行此函数时会创建一个称为执行环境的内部对象。一个执行环境定义了一个函数执行时的环境。函数执行时对应的执行函数都是独一无二的,所以多次调用同一个函数就会导致创建多个执行环境。当函数执行完毕后,执行环境就被销毁。
每个执行环境都有自己的作用域链,用于解析标示符。当执行环境被创建时,它的作用域链初始化为当前运行函数的[[scope]]属性的对象。这时会创建一个被称为“活动对象”。活动对象作为函数运行时的变量对象,包含了所有局部变量,命名参数,参数集合以及this。同时被推入作用域链的最前端。执行环境销毁后,活动对象也随之销毁。

在函数执行过程中,每遇到一个变量,都会经历一次标示符解析过程以决定从哪里获取或存储数据。而此搜索过程影响了性能。
标示符解析:
一个标示符所在的位置越深,它的读写速度也就越慢。
经验法则:如果某个跨作用域的值在函数中被引用一次以上,那么就把它存储到局部变量里。访问跨作用域的值,需要遍历作用域链往上找,会导致性能的下降,而通过局部变量存储一个跨作用域的值,使得查找次数减少,性能提升。
作用域链的改变:with语句、try-catch语句中的catch子句将临时改变作用域链,创建一个新的变量对象,并推入作用域链的首位,使得函数的所有局部变量处于第二作用域链的对象,导致访问代价提高。
动态作用域:with、try-catch的catch以及eval()被认为是动态作用域。动态作用域只存在于代码执行过程中,因此无法通过静态分析检测。某些优化的js引擎尝试通过分析代码来确定哪些变量可以在特定时候被访问。这些引擎试图避开传统作用域链的查找,取代以标示符索引的方式进行快速查找。而涉及动态作用域时,这种优化方式失效,脚本引擎切换回较慢的基于哈希表的标示符识别方式。
闭包:由于闭包的特性,将导致存在于闭包的[[scope]]属性中,活动对象无法被销毁,故引起更多的内存开销。因此在使用闭包时最需要关注的性能点:在频繁访问跨作用域的标示符时,每次访问都会带来性能损失。闭包的使用关系到内存和执行速度。

- 对象成员
js中的对象是基于原型的。原型是其他对象的基础,它定义并实行了一个新创建的对象所必须包含的成员列表。对象有两种成员类型:实例成员和原型成员。实例成员直接存在对象的实例中,原型成员则从对象的原型继承而来。
而在调用原型成员时,搜索过程会深入原型链中直到找到原型成员。而原型成员所在原型链的位置越深,访问所需时间就越多。
嵌套成员:js每次遇到点操作符时,嵌套成员会导致js引擎搜索所有对象成员。例如:location.href比window.location.href读取速度更快。
注:大部分游览器对于点表示法操作和括号表示法操作并没有明显区别,只有Safari中,点符号始终更快。
由于所有类似的性能问题都与对象成员有关,故因尽可能避免使用它们,或者说只在必要时使用对象成员。例如:多次读取同一个对象属性时,最佳做法是将属性值保存到局部变量以此来避免多次查找带来的性能开销。特别是处理嵌套对象成员时。
注:这种优化方式并不推荐用于对象的成员方法,因为许多对象方法使用this来判断执行环境,把一个对象方法保存在局部变量会导致this绑定到window,而this值的改变会使得js引擎无法正确解析它的对象成员,进而报错。
高性能javascript(记录二)的更多相关文章
- 高性能JavaScript笔记二(算法和流程控制、快速响应用户界面、Ajax)
循环 在javaScript中的四种循环中(for.for-in.while.do-while),只有for-in循环比其它几种明显要慢,另外三种速度区别不大 有一点需要注意的是,javascript ...
- 《高性能javascript》 领悟随笔之-------DOM编程篇(二)
<高性能javascript> 领悟随笔之-------DOM编程篇二 序:在javaSctipt中,ECMASCRIPT规定了它的语法,BOM实现了页面与浏览器的交互,而DOM则承载着整 ...
- JavaScript学习记录二
title: JavaScript学习记录二 toc: true date: 2018-09-13 10:14:53 --<JavaScript高级程序设计(第2版)>学习笔记 要多查阅M ...
- 《高性能Javascript》 Summary(二)
第四章.算法和流程控制 Algorithms And Flow Control 原因:代码整体结构是执行速度的决定因素之一.代码量少不一定运行速度快,代码量多不一定运行速度慢.性能损失与组织代码和具体 ...
- 高性能JavaScript(1)
---------------------------------------------------------------------------------------------------- ...
- 《高性能javascript》一书要点和延伸(上)
前些天收到了HTML5中国送来的<高性能javascript>一书,便打算将其做为假期消遣,顺便也写篇文章记录下书中一些要点. 个人觉得本书很值得中低级别的前端朋友阅读,会有很多意想不到的 ...
- 高性能JavaScript 重排与重绘
先回顾下前文高性能JavaScript DOM编程,主要提了两点优化,一是尽量减少DOM的访问,而把运算放在ECMAScript这一端,二是尽量缓存局部变量,比如length等等,最后介绍了两个新的A ...
- 【读书笔记】读《高性能JavaScript》
这本<高性能JavaScript>讲述了有关JavaScript性能优化的方方面面,主要围绕以下几个方面: 1> 加载顺序 2> 数据访问(如怎样的数据类型访问最快,怎样的作用 ...
- 《高性能javascript》学习总结
本文是学习<高性能javascript>(Nichols C. Zakes著)的一些总结,虽然书比较过时,里面的知识点也有很多用不上了,但是毕竟是前人一步步探索过来的,记录着javascr ...
- 《高性能JavaScript》--读书笔记
第一章 加载和运行 延迟脚本 defer 该属性表明脚本在执行期间不会影响到页面的构造,脚本会先下载但被延迟到整个页面都解析完毕后再运行.只适用于外部脚本 <script src="j ...
随机推荐
- Maven打包程序
1.src/main目录下建立scritps.config.assembly目录 scritps:存放脚本文件如批处理 assembly:打包配置文件 2.assembly目录下建立package ...
- djangocms安装技巧
首先python的版本要高一些,否则安装django-cms会报错 安装cmsinstaller不能够正常下载 利用virtualenv进行安装配置 注意中文的配置 djangocms配置中文 dja ...
- Node聊天程序实例06:server.js
作者:vousiu 出处:http://www.cnblogs.com/vousiu 本实例参考自Mike Cantelon等人的<Node.js in Action>一书. server ...
- Javascript 知识点整理
1.十进制和十六进制相互转换 /* 十六进制转十进制 */ var test = FF; var x = parseInt(test ,16); //方法一 x = parseInt('0x'+tes ...
- [地图SkyLine二次开发]关于IE内存限制问题(1G)
相信很多人也遇到过同样的问题,地图加载中,IE占用的内存一直增加,到了1G多一些的时候,IE就崩溃了. 在网上查阅了一番,有很多结果,下面归纳一下: a).64bit的IE最多可达到4G的内存,但Sk ...
- windows php线程安全和不安全,两个版本我也看不懂,记下来再说。
Windows下的PHP版本分两种:线程安全版本与非线程安全版本. 要论两者的区别,详细论说起来比较麻烦,从使用者的角度,记住什么时候用哪种版本的区别就可以了吧: 1.windows + IIS + ...
- pycharm快捷键、常用设置、包管理
pycharm快捷键.常用设置.包管理 在PyCharm安装目录 /opt/pycharm-3.4.1/help目录下可以找到ReferenceCard.pdf快捷键英文版说明 or 打开pychar ...
- join / left join / right join
1 可以自己join自己 SELECT * FROM table_1 t1join table_1 ton t.target_id = t1.target_id 2 join要双方都满足才可以出现结果 ...
- 【c#】对象转json字符串/字符串转Json对象
using Newtonsoft.Json; 一.Hashtable => Json Hashtable hash = new Hashtable(); hash.Add("key1& ...
- 有关Fragment的知识点
关于判断Fragment是否可见,可以尝试参考使用Fragment中的两个方法: final boolean isHidden() Return true if the fragment has be ...