【问题标题】:Freezing the elements of an array冻结数组的元素
【发布时间】:2018-08-30 15:53:53
【问题描述】:

我有一个由某些原始元素组成的数组:

const array = [1, 2, 3]

我希望能够暂时冻结该数组的一个元素并防止它被修改。但是一旦元素可以被修改,就应该有办法解冻这个值。

有办法吗?

对于那些将此问题标记为重复的人来说是题外话:

问题是关于冻结数组的元素,而不是整个数组。这不是关于冻结整个数组的问题的重复。

【问题讨论】:

  • Object.freeze() 满足您的要求吗?
  • 我的想法是制作一个包含原始值和锁定布尔值的自定义对象,如果它被锁定,则不允许更改,如果它未锁定,则允许更改。跨度>
  • @Leo 这不是重复的,他不想冻结整个数组。
  • @Andreas 只有数组定义是不变的。您仍然可以在 JS 中推送和弹出它的值。你只是不能重新分配给array,所以array = [5];会出错。

标签: javascript


【解决方案1】:

您不想冻结 ,您想冻结保存该值的 属性(在您的情况下是数组的 "1" 属性)。您可以使用 Object.defineProperty 重新定义不带 writable 标志的属性。为了让它再次可写,你用writable: true重新定义它:

const array = [1, 2, 3];
console.log("A", array.join(", ")); // 1, 2, 3

// Freeze it
Object.defineProperty(array, "1", {
  value: array[1],
  writable: false, // For emphasis (this is the default)
  enumerable: true,
  configurable: true
});
console.log("B1", array.join(", ")); // 1, 2, 3
array[1] = 42;                       // <== Doesn't change it
console.log("B2", array.join(", ")); // 1, 2, 3 (still)

// Thaw it
Object.defineProperty(array, "1", {
  value: array[1],
  writable: true,
  enumerable: true,
  configurable: true
});
console.log("C1", array.join(", ")); // 1, 2, 3
array[1] = 42;                       // <== Changes it
console.log("C2", array.join(", ")); // 1, 42, 3 (changed!)

如果执行分配的代码在严格模式下运行,则该分配将是一个例外:

"use strict";
const array = [1, 2, 3];
console.log("A", array.join(", ")); // 1, 2, 3

// Freeze it
Object.defineProperty(array, "1", {
  value: array[1],
  writable: false, // For emphasis (this is the default)
  enumerable: true,
  configurable: true
});
console.log("B1", array.join(", ")); // 1, 2, 3
array[1] = 42;                       // <== Doesn't change it
console.log("B2", array.join(", ")); // 1, 2, 3 (still)

// Thaw it
Object.defineProperty(array, "1", {
  value: array[1],
  writable: true,
  enumerable: true,
  configurable: true
});
console.log("C1", array.join(", ")); // 1, 2, 3
array[1] = 42;                       // <== Changes it
console.log("C2", array.join(", ")); // 1, 42, 3 (changed!)

但请注意,如果您的代码可以重新定义它以使其可写,那么其他任何人的代码也可以。

或者,给它一个 getter 和 setter,使其不可配置(因此没有其他人可以重新定义它),并维护一个标志:

const array = [1, 2, 3];
let elementValue = array[1];
let writable = true;
Object.defineProperty(array, "1", {
  get: function() {
    return elementValue;
  },
  set: function(newValue) {
    if (writable) {
      elementValue = newValue;
    }
  },
  enumerable: true,
  configurable: false // Again, emphasis
});

console.log("A", array.join(", ")); // 1, 2, 3
array[1] = 42;
console.log("B", array.join(", ")); // 1, 42, 3 -- it changed
writable = false;
array[1] = 67;
console.log("C", array.join(", ")); // 1, 42, 3 -- didn't change
writable = true;
array[1] = 94;
console.log("D", array.join(", ")); // 1, 94, 3 -- changed

当然,您会隐藏其中的一部分,而只公开数组本身。

【讨论】:

  • 特别感谢您详细说明第一句中的术语。
猜你喜欢
  • 2014-04-09
  • 1970-01-01
  • 1970-01-01
  • 2015-09-04
  • 2013-08-14
  • 1970-01-01
  • 1970-01-01
  • 2019-07-17
  • 2017-10-30
相关资源
最近更新 更多