【问题标题】:JSON and couplingJSON 和耦合
【发布时间】:2017-05-26 12:52:25
【问题描述】:

我不确定我是否正确理解了耦合。有人告诉我,如果我将数据移出到外部数据文件(如 JSON)中,它会减少整体耦合。 (我同意这一点。)

但是,如果我要创建一个对象来保存包含在 JSON 中的数据,其字段直接映射到 JSON 的结构,那是否仍会在对象和 JSON 之间创建紧密耦合的链接?

例如:

"images": [{
    "source" : "images/foo.png",
    "size" : "thumbnail",
    "alt" : "Foo"
},
{
    "source" : "images/bar.png",
    "size" : "thumbnail",
    "alt" : "bar"
}]

然后我们有一些对象,应用程序模型的一部分:

function FooBarImage (jsonObj) {
    this.source = jsonObj.source;
    this.size = jsonObj.size;
    this.alt = jsonObj.alt;
}

FooBarImage.prototype.doStuff = function () { ... }

这里,FooBarImage 对象知道 JSON 对象的内部格式。如果 JSON 数据的格式发生变化(例如,我们要添加一个新字段,或者重命名一个现有字段),我们是否也必须对构造函数进行更改?

是我误解了什么,还是有其他方法可以进一步解耦代码和数据?

【问题讨论】:

  • JSON 的全部意义在于传输对象。无需创建映射到 JSON 对象的第二个对象。
  • @Andreas 虽然你是对的,但“JSON 对象”这个词已经变得相当普遍,很明显 OP 想要说的是什么。虽然像您链接到的帖子这样的帖子内容丰富,但您的评论可能会被解读为扯皮。
  • @ScottMarcus 更准确地说,它实际上更像是将 JSON 数据映射到具有相同字段和一些方法的另一个对象。据我了解,JSON 是一个纯数据容器,所以我认为我不应该在 JSON 数据本身中有方法,因此需要另一个对象。
  • @Andreas 我知道;我只是为参数选择了名称jsonObj,以明确传递的是哪种数据。实际上,我可能只是使用data 或其他名称。

标签: javascript json decoupling


【解决方案1】:

您可以轻松地“反映”/“映射”您的 jsonObject(由提供的 JSON 字符串反序列化产生的文字对象)。您可以遍历对象属性并将它们分配给您的实例:

function FooBarImage (jsonObj) {
    Object.keys(jsonObj).forEach(function(prop) {
        this[prop] = jsonObj[prop];
    }
}

FooBarImage.prototype.doStuff = function () { ... }

示例:

function dirtyMap(fromObj, toObj) {
	Object.keys(fromObj).forEach(function(prop) {
		toObj[prop] = fromObj[prop];
	});
	return toObj; // chain me?
};

function FooBarImage (jsonObj) {
    dirtyMap(jsonObj, this);
};
FooBarImage.prototype.doStuff = function () { 
	console.log(this);
};

var json = `[{
    "source" : "images/foo.png",
    "size" : "thumbnail",
    "alt" : "Foo"
},
{
    "source" : "images/bar.png",
    "size" : "thumbnail",
    "alt" : "bar"
}]`
  , images = JSON.parse(json)
  , instances = images.map(function(img) { return new FooBarImage(img); })
  ;

instances.forEach(function(instance) { instance.doStuff(); });

另一种解决方案(当然还有其他解决方案)是使用工厂:

var createFooBarImage = function createFooBarImage(img) {
    var fooBarImage = Object.create(img);
    fooBarImage.doStuff = function () { 
        console.log(this);
    };
    return fooBarImage;
}

示例:

var json = `[{
	"source" : "images/foo.png",
	"size" : "thumbnail",
	"alt" : "Foo"
},
{
	"source" : "images/bar.png",
	"size" : "thumbnail",
	"alt" : "bar"
}]`
  , createFooBarImage = function createFooBarImage(img) {
		var fooBarImage = Object.create(img);
		fooBarImage.doStuff = function () { 
			console.log(this);
		};
		return fooBarImage;
	}
  , images = JSON.parse(json)
  , instances = images.map(function(img) { return createFooBarImage(img); })
  ;

instances.forEach(function(instance) { instance.doStuff(); });

【讨论】:

  • 这会处理嵌套对象/数组吗? Object.create() 不会在这里解决问题吗?而且,我不得不再次问,当您可以将所需的任何内容添加到从 JSON.parse() 解析的对象中时,为什么要这样做?
  • @ScottMarcus 确实,它不会,它只是一个示例,以说明这个概念。我添加了一个使用“某种”工厂模式的示例。但是,还有其他方法可以映射/扩展对象。
  • 为什么不简单地var newObj = Object.create(sourceObj)
  • @ScottMarcus 你可以,但你仍然没有FoorBarImg 的实例,newObj 没有 doStuff 方法吗?
  • 不,但这就是重点。使用Object.create() 代替您的克隆代码,然后将方法添加到返回对象的原型并完成。
猜你喜欢
  • 2017-05-09
  • 2010-09-07
  • 2012-12-20
  • 1970-01-01
  • 2013-12-25
  • 2017-10-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多