如何在JavaScript中创建一个高性能、不可变的数组



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

Object.freeze可能是我想要的,但jsperf报告说它比常规数组慢得多。

编辑:需要指定性能的标题。我们有很多WebGL电话要打!

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

您可以手动设置数组的赋值函数方法:

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';来修改数组):为什么需要一个不可变的数组?

让我换个说法,你想阻止谁修改数组?如果这是公开的,我会说制作你自己的对象,并公开你希望他们使用的方法。添加一个级别的函数调用来迭代对性能来说可以忽略不计,并且可以防止暴露赋值函数。

最后,如果你是保护自己的突变,那么你的编码是极端偏执。它增加了复杂性。防御编码(IMHO)更适用于系统外部的交互。防范自己的错误只会使代码变得更加复杂,因为你会事后猜测自己,而且在过多的if/else检查中往往缺乏一致性。

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

最新更新