【问题标题】:A good practice for protecting object literals and keeping them from being overwritten [closed]保护对象文字并防止它们被覆盖的好习惯[关闭]
【发布时间】:2012-09-28 21:12:42
【问题描述】:

我一直在对对象文字等进行一些研究。我正在创建一个具有来自我的玩家的各种属性的游戏。这些属性存储在多个组中,例如他的船和所有属性,他的武器和所有属性等。因此,我一直将这些属性存储到对象文字中。

我不希望我的对象值被覆盖。我在这里看到了一篇文章http://www.gabordemooij.com/jsoop.html,我很好奇这样的事情是否是一个健康的开始,可以防止对象值被轻易覆盖...

Cat = {
  createNew: function() {
    var cat = {};
    var sound = "meow"; //sound is local
    cat.makeSound= function(){
        //can reach sound from here
        alert( sound );
    }
    return cat;
  }
}

var cat = Cat.createNew();
cat.makeSound();
//but can't reach sound from here
alert(cat.sound); //fail!

【问题讨论】:

  • 查看对Revealing Object Pattern 的引用。这是您在这里尝试做的更平滑的变化。
  • 显示对象模式能否返回本地对象字面量值?

标签: javascript design-patterns object-literal revealing-module-pattern


【解决方案1】:

我在jsFiddle 中设置了一个小测试来演示显示对象模式是多么美妙:

var Test = (function(){
    var priv = "Banana";
    var public = "Orange";
    var pubobj = {name:"Cheese"};

    function constructor(){
        this.public = public;
        this.pubobj = pubobj;

        this.instance = {name:"Grape"};

        this.instanceMethod = function(){
            return priv;
        };
    };

    constructor.prototype.private = function(){
        return priv;
    };            

    return constructor;

})();

var myTest = new Test();

console.log(myTest.public);     //Orange
console.log(myTest.priv);       //undefined
console.log(myTest.private());  //Banana

var myTest2 = new Test();

console.log(myTest.public === myTest2.public);    //true (they are both primitives with the same value)
console.log(myTest.private === myTest2.private);  //true (the methods share the same instance)

myTest.public = "cheese";
console.log(myTest.public, myTest2.public);       // "cheese", "Orange" (overwriting the primitive doesn't change the primitive of myTest2)

myTest.pubobj.name = "Melon";                   
console.log(myTest.pubobj, myTest2.pubobj);       //the name property for both is now "Melon" (both test objects share the same instance of pubobj)

myTest.instance.name = "Raspberry";
console.log(myTest.instance, myTest2.instance);  // the name of myTest2.instance is unchanged

console.log(myTest.instanceMethod === myTest2.instanceMethod);​  // false (while identical, these methods have separate instances)

【讨论】:

  • 太棒了!谢谢Shmiddty!但是无论如何我们可以做你刚刚做的同样的事情,但每次都不需要创建一个“新”实例吗?
  • @blachawk 这有点违背了目的,不是吗?当然,您可能只有一个“玩家”,但游戏中的其他对象呢?子弹、敌人等。你会想要单独的实例,对吧?
  • 啊——你让我开始思考了。我可以称它为演员,然后为每种演员创建一个新实例!谢谢!
  • 请记住,您可以修改constructor 方法(或任何您想调用的方法)来获取参数,并将其存储为实例参数。
【解决方案2】:

它失败了,因为声音是一个不能在对象外部引用的局部变量。

如果你想引用它,你需要做一个getter。

Cat = {
  createNew: function() {
    var cat = {};
    var sound = "meow"; //sound is local
    cat.getSound= function(){
        //can reach sound from here
        return sound;
    }
    return cat;
  }
}


var cat = Cat.createNew();
alert(cat.getSound());

Cat = {
  createNew: function() {
    var cat = {};

    var props = {
        sound : "meow",
        foo : "bar"
    };

    cat.get= function(key){            
        return props[key];
    }
    return cat;
  }
}

var cat = Cat.createNew();
alert(cat.get("sound"));

【讨论】:

  • 在你的第一个例子中,如果 sound 是一个具有多个属性值的对象文字,然后返回,这是健康的做法吗?如果是这样,我会制作多个 var 对象来代表我的播放器的各种属性并返回每个对象。如果这听起来很愚蠢,请告诉我 - 第一次学习这些东西。
猜你喜欢
  • 2010-12-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-27
  • 2019-05-31
相关资源
最近更新 更多