高性能JavaScript(二)数据存取

数据存取

看到这里,有人会问数据存取为什么会影响性能?
其实数据存储的位置关系到代码执行的过程中的检索速度。JavaScript有四种基本的数据存储位置:
字面量,局部变量,数组元素,对象成员。
总的来说,字面量和局部变量的访问速度快于数组项和对象成员。(Firefox 3中对数组项进行了优化,访问其数组项会很快)。
所以我们从以下几个方面来优化代码:

  1. 管理作用域
    我们都知道,在JavaScript中,一切皆对象,函数也是一个对象,(是Function的一个实例对象)是对象,就会拥有属性,其中一个属性就是[[Scope]]。[[Scope]]是包含一个函数被创建作用域中对象的集合,也就是我们所说的作用域链。
    当函数被创建时,[[Scope]]会插入一个对象变量,也就是全局对象。
    当函数被执行时,会产生一个执行上下文(函数每次执行时的执行上下文都是独一无二的,多次调用产生多个执行上下文)。
    当执行上下文创建时,会将上层的作用域链复制到自己的[[Scope]]属性上,并生成一个包含局部变量,命名参数,参数集合及this的活动对象,插到作用域链最顶端,当函数执行结束时,执行上下文被销毁,活动对象也被销毁。
    在函数执行过程中,遇到每一个变量时,都会经历一次标识符解析的过程,而这个标识符解析就是影响性能的关键所在。标识符解析会在作用域链顶端开始查找变量,如果没有,会一次向下查找,知道找到该变量,如果没有找到就会视为未定义。所以查找局部变量是最快的,查找全局变量是最慢的,也是最消耗性能的。
    改变作用域链的方法:with、try-catch中的catch子句
    with虽然会将其作用域放在作用域最顶端,但是函数所有的局部变量都会到了第二个作用域中,使其访问局部变量时,代价更高了,所以,尽量避免该写法。
    try-catch也是一样,当try中的代码出错时,执行过程会自动跳转到catch中,将异常对象推到作用域顶端。
    闭包问题:闭包就是能够访问局部变量的函数,我们都知道从外不访问局部变量是不可能的,所以只能在一个函数中返回另一个函数,并且这个函数返回外部函数的变量,这也就是我们常见的闭包形式。上面说了,函数执行会产生执行上下文,函数执行结束会销毁执行上下文。当外部函数返回内部函数后,外部函数执行结束了,会销毁其执行上下文,但是这时的内部函数还没有执行,内部函数的作用域链上依旧有外部函数的作用域,所以内部函数依旧可以访问到外部函数的变量。闭包造成了作用域不释放,内存的泄露,所以要合理的使用闭包。

  2. 原型及原型链
    在JavaScript中,一切皆是对象,而对象又分为普通对象和函数对象。函数对象就是通过new Function()创建的对象为函数对象,其他都是普通对象。
    在对象中,都有一个内置__proto__属性,指向创建它的构造函数的原型。
    每一个函数对象都会有一个prototype属性,指向函数的原型对象。

    function Person() {}
    var person = new Person();
    person.__proto__ === Person.prototype    //true
    Person.prototype.__proto__ === Object.prototype    //true
    Object.prototype.__proto__ === null    //true
    person.toString()    //[object Object]
    

    在默认情况下,所有的对象都是对象的实例,并继承了所有的方法。__proto__属性将原型串成了一条链,也就是我们所说的原型链。这也就是上面为什么person.toString()返回[object Object]。当执行toString的方法时,会从对象实例开始搜索名为toString的成员,如果没有,就会沿着__proto__向上查找,直到找到toString成员,没找到返回undefined。
    在原型链中,查找对象成员时,没深入一层原型链,都会增加性能的消耗。

  3. 嵌套成员
    在javascript中经常会用到点运算符,如window.loaction.href,当遇到点运算符时,javascript引擎会搜索搜有的对象成员。location.href比window.loaction.href的读取速度要快。

总结:
在作用域链中,变量在作用域链中的位置越深,其所需时间就会越长。全局变量总是在作用域链最末端,访问速度最慢。
with和try-catch可改变作用域链,谨慎使用。
属性或方法在原型链中的位置越深,访问它的速度就会越慢。
嵌套成员会使javascript引擎搜索全部对象,尽量少用。
SO,局部变量时访问最快的,尽量使用局部变量,如果多次使用非局部变量,就将其var在局部变量中使用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值