对象的属性访问和普通变量访问之间的速度差异是什么?

时间:2012-08-26 00:42:51

标签: javascript arrays performance object properties

在完全定义我的问题之前,我必须说>> this question/answer<<我没有回答我的问题,而且我已经向自己证明了给定的答案与属性与变量或缓存属性的实际效果完全不匹配(见下文)。

我一直在使用HTML5画布,并且我在640x480区域内多次写入原始像素块。

根据一些教程的建议,最好缓存.data变量的ImageData属性(在这种情况下,它将是_SCimgData)。

如果我在SC_IMG_DATA中缓存该属性,我可以在Canvas中重复putImageData而没有问题;但如果我用_ScimgData.data直接重复访问它,代码的减速是显而易见的(花费将近1秒来填充单个640x480 Canvas):

var SomeCanvas  = document.getElementById("SomeCanvas");
var SCContext   = SomeCanvas.getContext("2d");
var _SCimgData  = SomeCanvas.getImageData(0, 0, 640, 400);
var SC_IMG_DATA = _SCimgData.data;



现在我有以下疑问:

我的代码是否会对其他类似的访问速度一样慢?

我需要一组对象数组,这些对象可以包含一个对象的几个“实例”(由常规实用程序函数创建),并且需要对象数组中的实例索引,要么创建/初始化它,或更新其属性。

我的具体例子如下:

var objArray=new Array();
var objArray[0]=new Object();
    objArray[0].property1="some string property";

for(var x=0; x<65536; x++)
 doSomething(objArray[0].property1, objIDX=0);

如果某些属性中包含的属性和函数被非常密集地调用(在一个毫秒内几次,当然使用setInterval和几个,那么该代码会变得像在Canvas情况下慢得令人无法接受吗? “计时器线程”以避免锁定浏览器?

如果是这样,还有什么其他替代方法可以加快主对象数组中多个对象的不同属性的访问速度?





编辑1(2012-08-27)

编辑1(2012-08-27)

编辑1(2012-08-27)

编辑1(2012-08-27)

感谢您的建议。我已经投票了,因为我怀疑它们对我正在进行的项目有用。

我正在思考一系列方法,主要使用Array而不是Object来构建实际的“基础对象”数组,并按数字寻址数组元素({{1} }而不是字符串数组键(arr[0])。

arr["zero"]

我会说,占据前10个数组元素的“对象”的“实例”;下一个“实例”将接下来的10个数组元素,依此类推(在自定义“构造函数”函数中创建初始化以添加新的数组元素块)。

我还将尝试使用jsPerf和JSHint来更好地了解哪种组合结果。

3 个答案:

答案 0 :(得分:4)

为了回答您的“疑惑”,我建议您使用JSPerf对代码进行基准测试。除非经过测试,否则无法通过代码单独判断程序是否比其他程序更快

另外,我建议你在构造过程中使用数组和对象的文字表示法而不是new表示法:

var objArray=[
    {
        property : 'some string property'
    }, {
        ...
    },
];

此外,根据您的代码,最好这样做,因为每次迭代使用相同的对象:

var obj = objArray[0].property1,
    objIDX = 0;

for(var x=0; x<65536; x++){
    doSomething(obj,objIDX);
}

答案 1 :(得分:2)

尽管可能进行浏览器优化,但访问对象的属性比访问局部变量(但不一定是全局变量或父函数的变量)更昂贵。

财产越深,你的表现就越受欢迎。换句话说,

for(var x=0; x<65536; x++) 
 doSomething(objArray[0].property1, objIDX=0); 

将通过缓存objArray[0].property1进行改进,而不是重复分配给objIDX

var prop = objArray[0].property1;
objIDX = 0;
for(var x=0; x<65536; x++) 
 doSomething(prop, 0); 

答案 2 :(得分:1)

我意识到这并没有完全回答你的问题(因为它已经被回答),但是你似乎正在寻找关于发生数千次的函数调用的速度改进(正如其他人发现这可能也在做)。我以为我会把它包含在这里,因为它违背了假设:

示例功能:

var go = function (a,b,c,d,e,f,g,h) {
  return a+b+c+d+e+f+g+h;
}

以下是您通常会调用重复函数的方法:

var i=500000; while(i--){
  go(1,2,3,4,5,6,7,8);
}

但是,如果这些参数的(或少数)没有为这个函数的特定用法而改变,那么这样做会好得多(从速度pov - 显然不是异步pov)

var i=500000; go.args = [1,2,3,4,5,6,7,8];
while(i--){
  go();
}

为了使上述功能正常工作,您只需对原始功能稍作修改即可:

var go = function (a,b,c,d,e,f,g,h, i) {
  if ( go.args ) {
    i = go.args;
    a = i[0]; b = i[1];
    c = i[2]; d = i[3];
    e = i[4]; f = i[5];
    g = i[6]; h = i[7];
  }
  return a+b+c+d+e+f+g+h;
}

第二个函数的运行速度明显更快,因为你没有传入任何参数(一个名为no args的函数可以很快启动)。从.args数组中提取值似乎并不是那么昂贵(除非你涉及字符串)。即使你更新了一个或两个args,它仍然要快得多,这使得它非常适合像素或图像数据处理,因为你通常只需要移动x和amp; Y:

var i=500000; go.args = [1,2,3,4,5,6,7,8];
while(i--){
  go.args[2] = i;
  go();
}

所以在某种程度上,这是一个示例,其中对象属性可以比本地变量更快 - 如果有点复杂和偏离主题;)