如何在JavaScript中创建高性能,不可变的数组?

时间:2014-04-24 00:44:57

标签: javascript arrays

假设我有一个经常使用的数组,例如单位矩阵,我想确保不会意外修改。如何创建无法修改的JavaScript数组?

Object.freeze可能就是我想要的,但是jsperf reports that it's much slower than a regular array

编辑:指定效果的标题是必需的。我们有很多WebGL要求!

编辑2:更具体地说,这是针对基于浏览器的WebGL游戏(因此性能要求),因此可以使用Chrome和Firefox的当前JavaScript解释器中的任何功能。关于代码审查的社会压力,绝对!但我们仍然是犯错误的人,偶尔会写错误的变量。

1 个答案:

答案 0 :(得分:4)

您可以手动设置数组的mutator方法:

var mutatorMethods = ['fill', 'pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'];

function preventMutation() {
  throw new TypeError('Array is immutable');
}

function makeImmutableArray(origArray) {
  mutatorMethods.forEach(function(method) {
    origArray[method] = preventMutation;
  });

  return origArray;
}

var foo = makeImmutableArray(['foo', 'bar', 'baz']);

以jsbin为例:http://jsbin.com/zeser/1/edit

然而,这只是对更大问题的釉面(考虑到仍然可以通过直接索引foo[0] = 'froboz';修改数组):为什么需要不可变数组?

让我重新说一下,你是谁试图阻止修改阵列?如果这是公开面对的,我会说你自己制作对象并公开你希望它们使用的各种方法。添加一级函数调用迭代可以忽略性能,并且可以防止暴露mutator函数。

最后,如果你保护自己的突变,那么你的编码是极端的偏执狂。它增加了复杂性。对于来自系统外部的交互,防御性编码更好地服务(恕我直言)。防范自己的错误只会使代码变得更加复杂,因为你会在第二次猜测自己,并且在过多的if / else检查中往往缺乏一致性。

相反,我通过制作你自己的类似对象并使用它来提供封装迭代对象的概念。