网络编程
位置:首页>> 网络编程>> JavaScript>> JScript下Array对象的性能问题(2)

JScript下Array对象的性能问题(2)

作者:hax 来源:hax的技术部落格 发布时间:2009-02-15 12:28:00 

标签:jscript,array,数组,性能,对象

之所以有这样的结果,是因为length减小时,引擎不仅仅是改变了length的值,而且要删除所有索引大于等于新的length的元素。

本来这件事情可以这样做(我相信大多数程序员的第一感觉也就是这样做):

function get_length() { return this._length }   
function set_length(len) {   
  if (len < 0 || len > 0xffffffff) throw RangeError()   
  if (len > this._length) {   
    this._length = len; return  
  }   
  while (len < this._length) {   
    delete this[--this._length]   
  }   
}

如果确实这样做的话,性能绝不会如此糟糕(不信你可以写个自己的MyArray来试验一下——用JS写出来的居然比built-in的C实现还要快)。

但是,JScript团队的程序员,据说认为JS的Array其实是稀疏数组,或者说就是一个hash——理论上也确实如此,所以采用了大概是这样的算法(以JS来示意):


function get_length() { return this._length }   
function set_length(len) {   
  if (len < 0 || len > 0xffffffff) throw RangeError()   
  if (len < this._length) {   
    for (var k in this) {   
      var i = toUint32(k)   
      if (i >= len) delete(this[k])   
    }   
  }   
  this._length = len   
}  

其中toUint32(s)将一个32位无符号整数的十进制字符串表达转为数字,如果转换失败则返回-1。【注意,此toUint32与parseInt不同,传入'0123'、'123.00'、'+123'、'1e4'等都会转换失败。】

这段代码遍历所有的key(因为Array本质上是把数字索引转换为字符串索引来保存的),如果这个key可以被转回无符号整数(也就是数字索引),则看看它是否大于指定的长度,大于的话就删掉。

好了,现在我们就不难理解为什么性能会与元素个数成正比了。假如一个50000个元素的数组,pop()了一下之后,居然也要遍历50000个元素!如果是在一个循环中不断pop()可想而知会有多慢。

0
投稿

猜你喜欢

手机版 网络编程 asp之家 www.aspxhome.com