保护封闭内的对象不被从外部修改
Protect object inside closure from being modified from outside
我创建这个对象是为了能够在其中存储数据,这具有一定的保护级别。只要新数据通过验证,任何人都可以获得它,任何人也可以设置它。
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
中的对象发生了变化,这使得我的整个概念变得毫无用处。我该如何解决这个问题?
这正是Object.freeze()
的作用。
来自MDN:
Object.freeze((方法冻结对象:也就是说,阻止新的属性不会添加到其中;阻止现有属性被移除;并阻止现有属性或其可枚举性、可配置性或可写性。在里面本质上,对象实际上是不可变的。该方法返回对象被冻结。
注意:IE v8及以下版本不支持Object.freeze((。
我的建议是,与其返回对象,不如返回可以为可读性设置名称空间的属性:
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
,它检查要设置的属性,并执行任何您想要的操作(返回并忽略、抛出错误等(
Object.freeze(objectName);
其中"objectName"是要冻结的对象的名称。
我通过将this.get
修改为以下来解决此问题
this.get = function(key){
return (data[key] instanceof Object) ? Object.create(data[key]) : data[key];
}
一个解决方案可以是返回对象的副本。
使用下划线/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);
}
第二种解决方案仍然不完美,因为它无法处理循环对象,并且克隆getters/ssetter等可能存在问题。但对于简单的情况,即使是第一种解决方案也可以。
- Firebase2(Firebase.google.com)推送通知-从外部管理
- 如何从外部页面激活非默认引导选项卡
- 图像可以从源<img src=""/>.TEXT可以在没有javascript的情况下从外部
- 将函数从onclick修改为onload
- 如何从外部url寻址数据
- 从外部函数渲染后更改ReactJS类的状态
- 为什么我从浏览器修改html/js时会多次发送ajax请求
- 使用ajax长轮询从外部API更新页面上的响应
- 在选择更改时更改从外部javascript生成的flash播放器
- 从外部js文件编辑现有的谷歌地图
- CkEditor复制/粘贴实现-从编辑器复制和从外部编辑器复制
- Javascript从外部站点获取html
- 如何在从外部连接时将外部文件包含到node-js项目中
- GWT:可以从外部JavaScript而不是JSNI调用Java方法吗
- 访问模块.从外部文件导出
- 从外部 txt 加载阵列
- 无法让 javascript 从外部文件工作
- Jquery:如何从内部到外部修改项
- 从外部站点修改html的Javascript
- 保护封闭内的对象不被从外部修改