代码之家  ›  专栏  ›  技术社区  ›  Eduard

冻结数组元素

  •  0
  • Eduard  · 技术社区  · 7 年前

    我有一些基本元素:

    const array = [1, 2, 3]
    

    我想暂时 冻结此数组的元素 并防止其被修改。但一旦允许修改元素,就应该有一种方法来解冻该值。

    有办法吗?

    1 回复  |  直到 7 年前
        1
  •  4
  •   T.J. Crowder    7 年前

    你不想冻结 价值 ,你想冻结 持有价值的 "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

    很自然,你会隐藏其中的一些内容,然后直接暴露数组本身。