繁体   English   中英

Javascript-创建不带引用的对象

[英]Javascript - Create object without reference

我在创建没有引用的Object实例时遇到问题。

我研究发现,很多人建议使用jQuery.extend来创建没有参考的对象。

请参阅: 在JavaScript中深度克隆对象的最有效方法是什么?

但就我而言,这并不成功。

这是我的代码JSBin

 var MyModel = (function() { MyModel = function() {}; var myModelObj = { prop1: null, prop2: { sub1: null, sub2: null } }; MyModel.prototype = { getProp1: function() { return myModelObj.prop1; }, getSub1: function() { return myModelObj.prop2.sub1; }, getSub2: function() { return myModelObj.prop2.sub2; }, setProp1: function(val) { myModelObj.prop1 = val; }, setSub1: function(val) { myModelObj.prop2.sub1 = val; }, setSub2: function(val) { myModelObj.prop2.sub2 = val; }, getObj: function() { return $.extend({}, myModelObj); }, setObj: function(json_obj) { myModelObj.prop1 = json_obj.prop1; myModelObj.prop2.sub1 = json_obj.prop2.sub1; myModelObj.prop2.sub2 = json_obj.prop2.sub2; }, setParam: function(prop1, sub1, sub2) { myModelObj.prop1 = prop1; myModelObj.prop2.sub1 = sub1; myModelObj.prop2.sub2 = sub2; } }; return MyModel; }()); var model1 = new MyModel(); model1.setParam('prop1', 'sub1', 'sub2'); var model2 = new MyModel(); model2.setParam('clone-prop1', 'clone-sub1', 'clone-sub2'); console.log("object 1"); console.log(model1.getObj()); console.log("object 2"); console.log(model2.getObj()); 

我的预期结果是

model1 = {
   prop1: 'prop1',
   prop2: {
      sub1: 'sub1',
      sub2: 'sub2'
   }
}

model2 = {
   prop1: 'clone-prop1',
   prop2: {
      sub1: 'clone-sub1',
      sub2: 'clone-sub2'
   }
}

但实际上, model1model2有相同的数据model2

有人可以指出我犯错的地方吗?

=== 更新 ===

@arcyqwerty的解决方案帮助我解决了创建引用时没有参考的问题。

 var MyModel = function() { this.prop1 = null; this.prop2 = { sub1: null, sub2: null }; }; MyModel.prototype = { getProp1: function() { return this.prop1; }, getSub1: function() { return this.prop2.sub1; }, getSub2: function() { return this.prop2.sub2; }, setProp1: function(val) { this.prop1 = val; }, setSub1: function(val) { this.prop2.sub1 = val; }, setSub2: function(val) { this.prop2.sub2 = val; }, getObj: function() { return $.extend({}, this); }, setObj: function(json_obj) { this.prop1 = json_obj.prop1; this.prop2.sub1 = json_obj.prop2.sub1; this.prop2.sub2 = json_obj.prop2.sub2; }, setParam: function(prop1, sub1, sub2) { this.prop1 = prop1; this.prop2.sub1 = sub1; this.prop2.sub2 = sub2; } }; var model1 = new MyModel(); model1.setParam('prop1', 'sub1', 'sub2'); var model2 = new MyModel(); model2.setParam('clone-prop1', 'clone-sub1', 'clone-sub2'); console.log("object 1"); console.log(model1.getObj()); console.log("object 2"); console.log(model2.getObj()); 

但是我也想在OOP使用encapsulation功能。 这意味着,我们只能通过get函数获取值对象,属性。 有可能在Javascript吗? 它解释了为什么我在模型内有一个对象(但它引用了同一对象)

非常感谢你!

尝试这个

var MyModel = function() {
  this.prop1 = null;
  this.prop2 = {
    sub1: null,
    sub2: null
  };
};

MyModel.prototype = {
  getProp1: function() {
    return this.prop1;
  },
  getSub1: function() {
    return this.prop2.sub1;
  },
  getSub2: function() {
    return this.prop2.sub2;
  },
  setProp1: function(val) {
    this.prop1 = val;
  },
  setSub1: function(val) {
    this.prop2.sub1 = val;
  },
  setSub2: function(val) {
    this.prop2.sub2 = val;
  },
  getObj: function() {
    return $.extend({}, this);
  },
  setObj: function(json_obj) {
    this.prop1 = json_obj.prop1;
    this.prop2.sub1 = json_obj.prop2.sub1;
    this.prop2.sub2 = json_obj.prop2.sub2;
  },
  setParam: function(prop1, sub1, sub2) {
    this.prop1 = prop1;
    this.prop2.sub1 = sub1;
    this.prop2.sub2 = sub2;
  }
};

var model1 = new MyModel();
model1.setParam('prop1', 'sub1', 'sub2');
var model2 = new MyModel();
model2.setParam('clone-prop1', 'clone-sub1', 'clone-sub2');
console.log("object 1");
console.log(model1.getObj());
console.log("object 2");
console.log(model2.getObj());

原始构造函数的问题是MyModel实例(尽管使用new关键字创建的不同对象)都共享相同的myModelObj (仅创建一次)。 使用此解决方案,每次您创建新的MyModel时都会创建新的字段。

这类似于让MyModel = function() { this.myModelObj = {...}; } MyModel = function() { this.myModelObj = {...}; }并使用this.myModelObj.prop访问字段,但是在那一点上, myModelObj有点多余,因为您可以直接在this设置属性。

另外,使用此解决方案,您无需说model1.getObj().prop就可以直接使用model1.prop (尽管也可以)

-

注意:我看到它也有点奇怪

var ClassName = (function() {
  ClassName = function() { ...; };
  ClassName.prototype = { ... };
  return ClassName;
})();

你这样做是有原因的吗

var ClassName = function() { ... };
ClassName.prototype = { ... };

我想如果您不想使用myModelObj污染名称空间,那么在原始代码中这是有道理的,但否则似乎没有必要。

-

编辑:封装

如果需要通过getter / setter设置对象的属性,则可以尝试如下操作:

var MyModel = function() {
  var privateObject = {
    prop1: null,
    prop2: {
      sub1: null,
      sub2: null
    }
  };
  Object.defineProperty(this, 'prop1', {
    get: function() { 
      console.log('Getting prop1 through getter');
      return privateObject.prop1;
    },
    set: function(value) {
      console.log('Setting prop1 through setter');
      privateObject.prop1 = value;
    }
  });
};

缺点是您将无法使用原型链共享getter / setter函数,这意味着您将有很多函数对象挂在身边。 对于少数实例,这可能很好(在性能方面)。 如果您的类具有子类,它也会影响继承。

如果您在没有defineProperty的平台上,也可以通过将var privateObject在构造函数中并使用var privateObject this.getProp1 = function() { return privateObject.prop1; } this.getProp1 = function() { return privateObject.prop1; }而不是原型中。 最终效果类似于使用defineProperty

-

编辑:或使用getter / setter语法

注意 :返回的对象不是 Finstanceof

function F() {
  var fields = { prop: null };
  return {
    get prop() {
      console.log("getter");
      return fields.prop;
    },
    set prop(value) {
      console.log("setter");
      fields.prop = value;
    }
  };
}
f = new F
f.prop = 123
f.prop

arcyqwerty答案的这种变体展示了数据的更深层封装。 需要权衡的是,每个实例都有自己的方法副本,而不是在“类”级别共享它们:

var MyModel = function() {
  var prop1 = null;
  var prop2 = {
    sub1: null,
    sub2: null
  };
  this.getProp1 = function() {
    return prop1;
  };
  this.getSub1 = function() {
    return prop2.sub1;
  };
  this.getSub2 = function() {
    return prop2.sub2;
  };
  this.setProp1 = function(val) {
    prop1 = val;
  };
  this.setSub1 = function(val) {
    prop2.sub1 = val;
  };
  this.setSub2 = function(val) {
    prop2.sub2 = val;
  };
  this.getObj = function() {
    return {
      prop1: prop1,
      prop2: {
        sub1: prop2.sub1,
        sub2: prop2.sub2
      }
    };
  };
  this.setObj = function(json_obj) {
    prop1 = json_obj.prop1;
    prop2.sub1 = json_obj.prop2.sub1;
    prop2.sub2 = json_obj.prop2.sub2;
  };
  this.setParam = function(_prop1, _sub1, _sub2) {
    prop1 = _prop1;
    prop2.sub1 = _sub1;
    prop2.sub2 = _sub2;
  };
};

你说,

但是我想知道我们如何保护Javascript属性?

我认为这是错误的问题。 JS是一种与Java或Ruby不同的语言,其关注点有所不同。 它至少是一种与OO语言相同的功能语言。 在编写JS时,您可能不应该看起来像在使用Java一样工作,而应学习其民俗习惯。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM