【问题标题】:Read-only from outside and not from inside从外部而不是从内部只读
【发布时间】:2015-04-03 11:21:05
【问题描述】:

看看这个对象

var bob = {
    name    : "Bob",
    age     : 18,
    talk    : function() {
        console.log("hi");
    },
    growOld : function() {
        this.age += 30;
    }
}

我可以访问bob.age 并使用bob.growOld()。但是,如果我希望 bob.age 从外部只读并从内部读取怎么办?例如bob.age = 20 不起作用,我只能使用bob 对象的方法更改age 属性。

我做了一些谷歌搜索并设法设置了一个只读属性。

var bob = {
    name    : "Bob",
    talk    : function() {
        console.log("hi");
    },
    growOld : function() {
        this.age += 30;
    }
}

Object.defineProperty(bob, "age", {
    enumerable      : false,
    configurable    : false,
    writable        : false,
    value           : 18
});

我不能用bob.age = 20改变age,但我也不能用方法改变它。 bob.growOld() 不会更改 age 属性。我认为将 configurable 设置为 true 可以解决问题,但事实并非如此。

有没有办法完成我在这里尝试做的事情?

【问题讨论】:

    标签: javascript object properties readonly


    【解决方案1】:

    JavaScript 提供了许多做事的方法,并且可能还有其他方法可以实现这一点,但这是我可以想到的使用 Object.defineProperty 和对象字面量的方法。

    基本上,您将 bob 声明为公共变量,然后使用 iife 在其中创建私有变量(“privateAge”)创建私有空间,然后向 bob 添加其他属性,这些属性本身将是公共的,但也可以访问 iife 的范围。

    接下来,在 iife 中,您使用 object.property 将要公开的属性声明为只读('age'),并重新定义 get 以返回 privateAge,这是关键,不要定义set 或定义它在被调用时执行其他操作。

    哦,我想我应该提一下,当使用bob.age 时调用get,当bob.age 与赋值运算符一起使用时调用set(例如bob.age = 100

    // Public out here
    var bob;
    // This is the iife
    (function() {
      // Private in here
      var privateAge = 17;
      bob = {
        name    : "Bob",
        talk    : function() {
            console.log("hi");
        },
        growOld : function() {
            privateAge += 30;
        }
      }
    
      Object.defineProperty(bob, "age", {
        get: function() { return privateAge; },
        set: function(newValue) { 
          // This is how read only from the out side is achieved
          // You could throw an error here or just omit set completely
          console.log("Not yours!");
        } 
      });
    
    }());
    
    console.log(bob.age)  // 17
    console.log(bob.privateAge) // undefined
    bob.age = 100 // Not yours!
    console.log(bob.age) // still 17
    bob.growOld(); 
    console.log(bob.age) // 47
    

    【讨论】:

    • 这在某种程度上是可行的,但我必须改变我的代码结构。最初,我使用构造函数来创建对象,并且在主对象内部调用了其他构造函数。我不知道我应该如何在我的代码中实现这个方法。我真的不想改变结构。 Actual code
    猜你喜欢
    • 2016-08-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多