我创建了这个对象,以便能够在其中存储具有一定程度保护的数据。任何人都可以得到它,任何人都可以设置它,只要新数据通过验证。
MF.factory = new function(){
var data = {
SITE_URL: document.URL.replace(/(https?:\/\/.+?)\/.*/, '$1'),
xhrSettings: {
type: 'GET',
error: function(){},
response: function(){},
max_upload_file_size: 8388608
}
}
this.get = function(key){
return data[key];
}
this.set = {
xhrSettings: {
type: function(type){if(type in {POST:0,GET:0,PUT:0}) data.xhrSettings.type = type;},
error: function(func){if(typeof func === 'function') data.xhrSettings.error = func;},
response: function(func){if(typeof func === 'function') data.xhrSettings.response = func;},
max_upload_file_size: function(size){if(!isNaN(size)) data.xhrSettings.max_upload_file_size = size;}
}
}
};
例如,现在我可以获得SITE_URL
,但我无法设置它。这是我正在寻找的那种限制。我可以设置xhrSettings.type
,只要它是POST,GET或PUT。
MF.factory.set.xhrSettings.type("DGD"); // No effect
MF.factory.set.xhrSettings.type("POST"); // data.xhrSettings.type = "POST"
但是,如果我这样做
a = MF.factory.get('xhrSettings');
a.type = "DGD";
console.log(MF.factory.get('xhrSettings'));
我看到data
内的对象发生了变化,这使我的整个概念变得毫无用处。我该如何解决这个问题?
答案 0 :(得分:1)
这正是 Object.freeze()
的用途。
来自MDN:
Object.freeze()方法冻结一个对象:即阻止new 属性被添加到它;防止现有属性 被删除;并防止现有的属性,或他们的 可更改性,可配置性或可写性。在 本质上,对象是有效不可变的。该方法返回 被冻结的物体。
注意:IE v8及更低版本不支持Object.freeze()。
答案 1 :(得分:1)
我的建议不是返回对象,而是返回属性本身可以命名为可读性的属性:
type = MF.factory.get( 'xhrSettings.type');
type = "DGD";
console.log(MF.factory.get('xhrSettings.type'));
这意味着您的data
对象具有平面属性:
var data = {
SITE_URL: document.URL.replace(/(https?:\/\/.+?)\/.*/, '$1'),
"xhrSettings.type": 'GET',
"xhrSettings.error": Function.prototype,
"xhrSettings.max_upload_file_size": 8388608
}
等
并且set
成为一个实际的function
,用于检查尝试设置哪个属性并执行您想要的任何操作(返回并忽略,抛出错误等)
答案 2 :(得分:0)
Object.freeze(objectName);
其中“objectName”是您要冻结的对象的名称。
答案 3 :(得分:0)
我通过将this.get
修改为以下
this.get = function(key){
return (data[key] instanceof Object) ? Object.create(data[key]) : data[key];
}
答案 4 :(得分:0)
一种解决方案是返回对象的副本。
使用下划线/ lodash,您可以使用_.clone()
,所以:
this.get = function(key){
return _.clone(data[key]);
}
请记住,尽管该克隆只执行浅拷贝。所以,如果你需要它,你可以滥用jquery extend
,并添加数组检查:
this.get = function(key){
var x = data[key];
return typeof x !== 'object' ? x :
$.extend(true, (Array.isArray(x) ? [] : {}), x);
}
这第二个解决方案仍然不完美,因为它不会处理圆形对象,并且可能存在克隆getter / setter等问题。但对于简单的情况,即使第一个解决方案也没问题。