Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/457.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 保护闭包内的对象不被外部修改_Javascript - Fatal编程技术网

Javascript 保护闭包内的对象不被外部修改

Javascript 保护闭包内的对象不被外部修改,javascript,Javascript,我创建这个对象是为了能够在其中存储数据,它具有一定的保护级别。任何人都可以获得它,只要新数据通过验证,任何人都可以设置它 MF.factory = new function(){ var data = { SITE_URL: document.URL.replace(/(https?:\/\/.+?)\/.*/, '$1'), xhrSettings: { type: 'GET', error: functi

我创建这个对象是为了能够在其中存储数据,它具有一定的保护级别。任何人都可以获得它,只要新数据通过验证,任何人都可以设置它

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;}
        }
    }
};
例如,现在我可以获取
站点的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
中的对象发生了变化,这使得我的整个概念变得毫无用处。我如何解决这个问题?

这正是的目的

来自MDN:

方法冻结一个对象:也就是说,阻止新的 不向其添加属性;防止现有属性被删除 被移除;并阻止现有属性或其 无法更改的可枚举性、可配置性或可写性。在里面 本质上,对象是有效地不可变的。该方法返回 被冻结的物体

注意:IE v8及以下版本不支持Object.freeze()

Object.freeze(objectName);

其中“objectName”是要冻结的对象的名称。

我的建议是,与其返回对象,不如返回本身可以命名为可读性的属性:

  type = MF.factory.get( 'xhrSettings.type');
  type = "DGD";
  console.log(MF.factory.get('xhrSettings.type'));
这意味着您的
数据
对象具有平面属性:

var data = {
    SITE_URL: document.URL.replace(/(https?:\/\/.+?)\/.*/, '$1'),
    "xhrSettings.type": 'GET',
    "xhrSettings.error": Function.prototype,
    "xhrSettings.max_upload_file_size": 8388608
}
等等


set
变成了一个实际的
函数
,它检查要设置的属性,并执行您想要的任何操作(返回和忽略、抛出错误等)

我通过修改
这个来解决它

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);
}

第二种解决方案仍然不是完美的,因为它不会处理循环对象,克隆getter/setter等可能会有问题。但对于简单的情况,即使是第一种解决方案也可以。

@Andy-是的,谢谢你指出。我会将其添加到答案中。但即使使用我的
set
函数,也不会使对象不可更改吗?该函数本应更改对象,但会首先验证传入的数据?它在文档中,但有时人们不会深入页面;)@php_nub_qq-是的,它将使对象完全不可变。@php_nub_qq-a)重新构造应用程序,以便将对象的冻结副本传递给读卡器作用域-或者-b)不要在名称空间之外公开setter,只返回getter作为对象方法的一部分。
MF.factory.get('xhrSettings.type')
为我返回
未定义的
:/嗯,是的,你必须更改你的代码。您的
数据
对象需要具有原始属性。我更新了答案来说明这一点。这是一个好主意,但我需要能够从
数据中返回整个对象,以便扩展其他对象并填充,然后在
get
中克隆对象。不过,此代码不适用于数组<代码>data.props=[1,2,3];x、 获得(‘道具);//[undefined,undefined,undefined]
@c69它确实适合我。它返回一个对象而不是数组,但是键值对是相同的,所以我认为这不是问题,除非你想使用
数组。prototype
,在这种情况下,我需要进一步调整它