[英]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'
}
}
但实际上, model1
和model2
有相同的数据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语法
注意 :返回的对象不是 F
的instanceof
。
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.