在JavaScript中处理点/小向量的最有效方法是什么?

7

目前我正在创建一个基于Web(= JavaScript)的应用程序,该应用程序使用了许多“点”(=小的、固定大小的向量)。基本上有两种明显的表示方式:

var pointA = [ xValue, yValue ];

并且

var pointB = { x: xValue, y: yValue };

那么稍微解释一下我的观点,会是这样:

var pointAtrans = [ pointA[0] + 3, pointA[1] + 4 ];
var pointBtrans = { x: pointB.x + 3, pointB.y + 4 };

从程序员的角度来看,两者都很容易处理(对象变量稍微更易读,特别是当我主要处理二维数据时,很少有三维和几乎没有四维 - 但从始至终它都适合于x、y、z和w)。

但我的问题是:
从语言角度来看,什么是最有效的方式 - 理论上和在实现中?
内存需求是多少?
数组与对象的设置成本如何?
...

我的目标浏览器是FireFox和基于Webkit的浏览器(Chromium、Safari),但在IE和Opera下也有一个良好(=快速)的体验不会有坏处...


2
我的感觉是对象占用的内存较少:对象是JS中的基本数据结构。数组是建立在对象之上并提供额外的方法。但是差异可能是微不足道的。 - Felix Kling
2
额外的方法保存在Array.prototype上。没有任何数组会直接拥有它们。 - gblazex
3个回答

6

创建数组速度更快,但是如果考虑访问时间则相反。同时注意,构造函数形式的创建和访问速度较快。在现代实现中,它兼具两者的优点:new Vector(x, y) - [测试]alt text

测试浏览器:Chrome 10,Firefox 3.6,Firefox Beta 4.0b9,IE 9 Preview 7,Opera 11


3
在Chrome 8中,访问数组和对象几乎没有区别。但是,创建数组要快得多。 - Felix Kling
1
@Chris:我刚意识到,arr['0']较慢其实是有道理的——因为由于数组对象的特殊性质,还会执行ToString(ToUint32('0')) === '0'。也许Firefox已经优化了这种冗余。 - Andy E
1
@Andy:发现它是索引属性的成本在解析时完成,因此它没有运行时成本(这是所有jsperf测试)。然而,我怀疑访问测试对于设置属性的成本而言更偏向于对象本身而非访问本身。 - gsnedders
1
@Andy:当然,显而易见的是Firefox 3.6在解析时不会这样做,但其他实现方式会。 - gsnedders
1
@Andy:如果它是一个变量,你就无法这样做,但是arr['0']是一个在解析时已知的常量,因此ToString(ToUint32('0'))可以在解析时确定。 - gsnedders
显示剩余9条评论

2

我猜使用数组可以获得更好的性能。

然而,你的数组示例中的代码已经比对象示例中的代码难以阅读得多。收益可能很小,因此建议您进行一些基本的基准测试和粗略的计算,以实现权衡。

首先,您可以:

  • 启动计时器
  • 构造1千个随机[X,Y] 数组
  • 访问它们的字段100万次。
  • 重复使用对象并进行比较。

(!)- 为什么基准测试非常有用的一个很好的例子:数组确实更适合创建,但对象更适合访问,这可能非常重要(取决于您的需求)。galambalazs为此编写了一个很棒的测试:http://jsperf.com/object-vs-array


1
你说得对,只有基准测试才能给出“答案”- 但是JavaScript目前在获得更快和更快的实现方面具有巨大的动力,我担心基于当前基准测试的设计决策很快就会过时... - Chris
1
你说得对。实际上,除非我正在实现某些特殊性能需求的东西(或者权衡的程度迫使我这样做),否则我总是更倾向于节省开发人员的时间而不是机器的时间,特别是在原型阶段。像任何软件开发一样,良好的封装和避免重复代码,以便稍后进行重构时不会太痛苦。 - Kyle Wild
使用Google V8,我认为类版本会和编译后的C++代码一样快。 - Alexandre C.

2
感谢所有的答案和意见。特别要提到的是由galamalazs编写的测试结果非常有趣:http://jsperf.com/object-vs-array/2 综合考虑,我们得出以下结论:
  • 数组应该使用数字索引,而不是字符串索引(arr[0] vs. arr['0'])
  • 对象形式与数组形式之间的性能差异主要取决于实现方式而不是类型。
  • 没有赢家,这取决于具体的实现方式。
  • 今天已知的浏览器的未来实现也可能改变胜者 - 不管哪种情况。
  • 在 Chromium 上,数组将使用对象的一半内存 - 但我们正在谈论一百万个实例的40 MB和80 MB - 每个实例约为40至80字节。
  • 其他 JavaScript 实现的内存消耗未知 - 但它很可能与性能一样有所不同。
因此,在最终决定时,两种选项都是合理的,只有代码可读性会影响决策!
如果主要用于存储带有微不足道的工作的数据(如我的当前项目),则应采用对象方式。一个mouse.xmouse.y可以轻松地显示开发人员的意图。
在大多数基于数学的应用程序中,如向量数学和坐标变换(特别是进入3D),最好的方法是数组。因为像矩阵乘法这样的事情看起来更符合开发者的本意。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接