javascript:私有成员和只读属性

时间:2013-02-28 17:36:38

标签: javascript oop design-patterns clone

SCENARIO

我有这门课:

var AssocArray = function(){
    var collection = new Object();

    this.add = function(id, o){
        collection[id] = o;
    }

    this.remove = function(id){
        delete collection[id];
    }

    this.getById = function(id){
        return collection[id];
    }

    this.get = function(){
        var res = collection;
        return res;
    }
}

var myAssoc = new AssocArray();
myAssoc.add("11",{ "packageId": "11", "machineId": "1", "operationType": "Download"});
myAssoc.add("12",{ "packageId": "12", "machineId": "1", "operationType": "Download"});
myAssoc.add("14",{ "packageId": "14", "machineId": "1", "operationType": "Download" });

if(myAssoc.getById("20")) myAssoc.remove("20");
if(myAssoc.getById("11")) myAssoc.remove("11");

console.log(myAssoc.get());  //returns Object {12: Object, 14: Object}

问题

一切正常。但如果我这样做:

(myAssoc.get())[10] = {};
console.log(myAssoc.get());  //returns Object {10: Object, 12: Object, 14: Object}!!

最终修改了私有成员collection。这是意料之外的(也是不必要的!)。

  • 出了什么问题?
  • 如何让get()返回collection成员的副本,而不是成员本身?

修改

我已阅读此question。因此,克隆collection成员可以完成这项工作。在设计模式中是否有另一种方法来保护私有成员和相关的只读属性?

3 个答案:

答案 0 :(得分:2)

没有什么是错的,这应该是标准的Javascript行为(我认为它与这个JS闭包的东西有关)。 :)

你必须手动克隆对象(我认为),如果你不想使用jQuery和东西......并且浅拷贝就足够了

function clone(obj)
{
    var cloneObj = {};
    for(var prop in obj )
    {
        cloneObj [prop] = obj[prop];
    }
    return cloneObj;
}

对于DeepCopies和东西你必须克隆那些属性或编写一个函数,你可以附加到对象原型,并在属性上调用克隆等等.... 在我看来,对于Deepcopies来说,最好使用jQuery,如果你在你的Page / Project /...中使用它,那就更好了。

答案 1 :(得分:0)

请参阅this回答。

this.get = function() {
   return jQuery.extend({}, collection);
});

答案 2 :(得分:0)

在javascript中,对象应该通过引用传递而不是传递值。所以,有一个参考。您可以修改get函数,如下所示将对象序列化为JSON字符串,然后将其反序列化为对象以克隆对象。所有没有任何第三方库的浏览器都支持JSON.stringifyJSON.parse

this.get = function(){
 var s = JSON.stringify(collection);
 return JSON.parse(s);
}

如果您在网站中包含了jquery,则可以使用$.extend功能 参考:http://api.jquery.com/jQuery.extend/

this.get = function(){
 return $.extend({}, collection);
}