javascript的数据访问
在javascript中有四种基本的数据访问位置:
1.直接量:
直接量仅仅代表自己,而不存储于特定位置。 JavaScript 的直接量包括:字符串,数字,布尔值,对象,
数组,函数,正则表达式,具有特殊意义的空值,以及未定义。
2.变量:
开发人员使用var 关键字创建用于存储数据值。
3.数组项
具有数字索引,存储一个JavaScript 数组对象。
4.对象成员
具有字符串索引,存储一个JavaScript 对象。
在大多情况下,对一个直接量和一个局部变量数据访问的性能差异是微不足道的。访问数组项和对象成员的代价要高一点,具体高多少,很大程序上依赖于浏览器。
几个重要概念:作用域链,标识符(此处不作详解,具体翻阅相关书籍)
标识符识别性能:
标识符识别不是免费的,事实上没有哪种电脑操作可以不产生性能开销。在运行期上下文的作用域链中,一个标识符所处的位置越深,它的读写速度就越慢。所以,函数中局部变量的访问速度总是最快的,而全局变量通常是最慢的(优化的JavaScript 引擎在某些情况下可以改变这种状况)。请记住,全局变量总是处于运行期上下文作用域链的最后一个位置,所以总是最远才能触及的。对所有浏览器来说,一个标识符所处的位置越深,读写它的速度就越慢
例子:
function initUI(){ var bd = document.body, links = document.getElementsByTagName_r("a"), i = 0, len = links.length; while(i < len){ update(links[i++]); } document.getElementById("go-btn").onclick = function(){ start(); }; bd.className = "active"; }
此函数包含三个对document的引用,document是一个全局对象,搜索此变量,必须要遍历整个作用域链,直到最后在全局变量对象中找到它。你可以通过将全局变量的引用存储在一个局部变量中,然后局部变量
代替全局变量。
function initUI(){ var doc = document, bd = doc.body, links = doc.getElementsByTagName_r("a"), i = 0, len = links.length; while(i < len){ update(links[i++]); } doc.getElementById("go-btn").onclick = function(){ start(); }; bd.className = "active"; }
改变作用域链:
1.使用with表达式(不建议使用)
function initUI(){ with (document){ //avoid! var bd = body, links = getElementsByTagName_r("a"), i = 0, len = links.length; while(i < len){ update(links[i++]); } getElementById("go-btn").onclick = function(){ start(); }; bd.className = "active"; } }
通过将document 对象传递给with 表达式,一个新的可变对象容纳了document 对象的所有属性,被插入
到作用域链的前端。这使得访问document 的属性非常快,但是访问局部变量的速度却变慢了,例如bd 变
量。正因为这个原因,最好不要使用with 表达式。正如前面提到的,只要简单地将document 存储在一个
局部变量中,就可以获得性能上的提升。
2.try-catch表达式的catch子句:
当try 块发生错误时,程序流程自动转入catch 块,并将异常对象推入作用域链前端的一个
可变对象中。在catch 块中,函数的所有局部变量现在被放在第二个作用域链对象中。
try { methodThatMightCauseAnError(); } catch (ex){ handleError(ex); //delegate to handler method }
请注意,只要catch 子句执行完毕,作用域链就会返回到原来的状态。
handleError()函数是catch 子句中运行的唯一代码。此函数以适当方法自由地处理错误,并接收由错误产
生的异常对象。由于只有一条语句,没有局部变量访问,作用域链临时改变就不会影响代码的性能。
动态作用域:(不建议使用)
无论是with 表达式还是try-catch 表达式的catch 子句,以及包含()的函数,都被认为是动态作用域。一
个动态作用域只因代码运行而存在,因此无法通过静态分析(察看代码结构)来确定(是否存在动态作用
域)
嵌套对象成员会造成重大性能影响,尽量少用。
一个属性或方法在原形链中的位置越深,访问它的速度就越慢。
一般来说,你可以通过这种方法提高JavaScript 代码的性能:将经常使用的对象成员,数组项,和域外变量存入局部变量中。然后,访问局部变量的速度会快于那些原始变量。