【问题标题】:How to create static array in JavaScript如何在 JavaScript 中创建静态数组
【发布时间】:2020-05-16 10:20:21
【问题描述】:

我正在尝试创建一个静态数组。但我发现它可以在运行时增加数组中的项目。如何在 JavaScript 中实现静态数组?为什么数组在 JavaScript 中是可变的?

var a = [];
//var a = new Array(3);
for (var i = 0; i < 5; i++) {
  //a.push(i);
  a[i] = i;
}

document.write(a);

【问题讨论】:

  • 你的意思是说数组元素的.length在数组初始定义后应该不能再增加了吧?
  • @guest271314,是的。

标签: javascript jquery


【解决方案1】:

您可以使用Object.freeze 冻结数组:

"use strict";
var a = Object.freeze([0, 1, 2]);
console.log(a);
try {
  a.push(3);     // Error
} catch (e) {
  console.error(e);
}
try {
  a[0] = "zero"; // Error
} catch (e) {
  console.error(e);
}
console.log(a);

不允许

  • 更改现有属性,无论是它们的值还是它们的其他特性,例如它们是否可扩展等。
  • 添加或删除属性

查看链接了解完整详情。如果您只是希望保持大小固定但确实希望允许更改条目的值,只需使用 Object.seal 代替。

请注意,尝试更改现有属性是否会导致错误(相对于静默失败)取决于您是否处于严格模式。

freezeseal 是在 ES5(2009 年 6 月)中引入的,因此应该出现在任何最新的浏览器中。过时的浏览器不会有它们。

【讨论】:

  • @TJCrowder 使用Object.create() 可以实现同样的效果吗?也就是说,.freeze.seal 对对象的原型或属性做了什么?
  • @guest:你不能使用Object.create 创建一个真正的数组实例,所以不,你不能用Object.create 这样做。 (您可以创建一些看起来很像数组的东西。)freezeseal 做什么,请按照上面的链接或参考规范。
  • 这能实现一些优化吗?
  • @Oriol:谢谢,一次发生太多事情的经典案例。 :-)
  • @RegisPortalez:完全有可能,但我不知道有什么具体的。但请考虑:如果 JavaScript 引擎知道无法更改属性(例如,a[0])(如果您使用的是 ES2015,最好将 a 设为 const,因此无法将其更新为指向一个新数组),并且您在某些代码中反复引用a[0],那么引擎可以选择缓存该值。
【解决方案2】:

使用最新的 JS 语法(旧浏览器需要 polyfill):

var list = Object.seal([1,2,3])

Object.seal 防止对 Object 进行进一步更改。

【讨论】:

    【解决方案3】:

    听起来你想要一个immutable 数组。

    大多数语言都有不可变的集合,无论是内置的还是来自库的。 JS 通常不包含它们,但 Facebook 提供了一个库,其中包含所有典型的不可变集合类型。

    虽然 immutablejs 本身没有数组类型,但它确实有更传统的 List

    const staticArray = List([0, 1, 2, 3, 4]);
    

    【讨论】:

      【解决方案4】:

      您可以使用Object.defineProperties() 在属性描述符处设置writable:falseconfigurable:falseObject.preventExtensions() 以防止将新属性添加到数组或对象中。

      "use strict";
      const ro = obj => {
        const props = {};
        const length = obj.length || Object.keys(obj).length;
        const entries = Array.isArray(obj) 
                        ? [...obj, length].entries() 
                        : Array.from(Object.keys(obj), prop => [prop, obj[prop]]);
        for (let [key, value] of entries) {
          props[key === length ? `length` : key] = {
            value: value,
            configurable: false,
            writable: false
          }
        }
              
        return Object.preventExtensions(Object.defineProperties(obj, props));
      };
      
      let arr = ro([1,2,3]);
      try {
        console.log(`arr[0]:${arr[0]}`);
        console.log(`try to set arr[0] to ${arr[0] = 4}`);
      } catch (e) {
        console.error(e)
      }
      
      try {
        console.log(`try to .push() to arr ${arr.push(4)}`);
      } catch (e) {
        console.error(e)
      }
      
      try {
        console.log(`try to set .length of arr ${arr.length = 4}`);
        console.log(arr.length);
      } catch (e) {
        console.error(e)
      }
      
      try {
        console.log(`try to delete of arr[1] ${delete arr[1]}`);
        console.log(arr.length);
      } catch (e) {
        console.error(e)
      }
      
      console.log(JSON.stringify(arr, null, 2));
      
      let obj = ro({a:1, b:2, c:3});
      
      try {
        console.log(`obj["c"]:${obj["c"]}`);
        console.log(`try to assign 4 to obj["c"]:${obj["c"] = 4}`);
      } catch (e) {
        console.error(e)
      }
      
      try {
        console.log(`try to assign property "d" to obj:${obj["d"] = 4}`);
      } catch (e) {
        console.error(e)
      }
      
      try {
        console.log(`try to delete property "b" of obj:${delete obj["b"]}`);
      } catch (e) {
        console.error(e)
      }
      
      console.log(JSON.stringify(obj, null, 2));

      【讨论】:

      • ……或者只是 const ro = Object.freeze 做同样的事情
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-20
      • 1970-01-01
      • 1970-01-01
      • 2014-03-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多