是否应该在应用程序逻辑处理之前克隆输入数据对象?

Should be an input data object cloned before it's processed by application logic?

我从事一个开源项目 - 又名对象文档映射器。 ODMjavascript 中,我正面临着一个我为之挣扎的设计决定(而不是 simple 而不是 easy)。

ODM中你可以定义一个Model对象来描述你在数据库中的数据文件。创建新的 Model 实例对象时,您可以通过参数传入它的数据值。
伪代码:

var data = {
    username: 'james'
    email: 'james@email.com',
    country: {
        code: 'US',
        city: ''
    } 
};
// In case the data object would not be cloned, it would be mutated by the ODM
var user = new UserModel(data);

现在,我面临的决定是是否在应用程序 (ODM) 处理模型之前自动克隆模型中的 data 对象。我倾向于选择不克隆输入数据。我觉得在 javascript 社区中,克隆数据通常比必要的数据更受欢迎,因为它可以为最终用户提供 easy(而不是 simple)的东西。从我的研究中,我发现一些类似且受欢迎的项目决定克隆数据,但我不确定这是正确的选择,因为模型可能具有大型和复杂的数据模式,但它没有任何区别如果有数十个 Model 实例对象,我认为在处理例如数百个 Model 对象时可能会出现问题。

我很想听听你对这个话题的推理,你的选择是什么?
如果您已经看到另一个答案,请不要犹豫,写下您的想法!
谢谢!

如果你继续使用输入对象来保存实体的数据,如果你不克隆对象,你将面临如下问题:

var UserModel = function(data) {
  this.data = data;
}
UserModel.prototype.getUsername = function() {
  return this.data.username;
}

var data = {username: 'james'};
var james = new UserModel(data);

data.username = 'john';
var john = new UserModel(data);

console.log(james.getUsername()); // "john"
console.log(john.getUsername());  // "john"

这可能会导致一些并不总是很明显的严重错误。


在我看来,最干净的方法不是克隆,而是从对象中提取相关信息并将其直接保留为成员属性:

var UserModel = function(data) {
  this.username = data.username;
  this.email = data.email;
}
UserModel.prototype.getUsername = function() {
  return this.username;
}
UserModel.prototype.getEmail = function() {
  return this.email;
}

更好的是,将属性显式声明为构造函数的参数:

var UserModel = function(username, email) {
  this.username = username;
  this.email = email;
}