我想用原型继承新的对象实例。
测试用例:
var MyObj = function() {}
MyObj.prototype.objName = {}
// I want this to be a different object for each instance of MyObj
var o1 = new MyObj (),
o2 = new MyObj ();
o1.objName['a'] = 1;
o2.objName['a'] = 2;
alert(o1.objName['a']) // 2
alert(o1.objName === o2.objName) // true
这意味着,在原型对象不继承它的拷贝,而是作为参考。
我知道,通常你可以不喜欢这样。
var MyObj = function() {
this.objName = {}
}
var o1 = new MyObj(),
o2 = new MyObj();
alert(o1.objName === o2.objName) // false
这工作得很好,但对我来说,这是不是一种选择。 我真的需要定义OBJNAME的MyObj中的功能外。
我设法“解决”这个问题
MyObj.prototype.objName = function() {
if ( this._objName === undefined ) {
this._objName = {};
}
return this._objName;
}
var o1 = new MyObj(),
o2 = new MyObj();
o1.objName()['a'] = 1;
o2.objName()['a'] = 2;
alert(o1.objName()['a']) // 1
但是,这是不是很漂亮,这个代码的性能要差很多。
有没有什么办法,以更优雅解决这个问题?
这意味着,在原型对象不继承它的拷贝,而是作为参考。
在原型没有被复制-原型继承的整个概念是属性引用原型对象的共享属性。 所以,如果你想有一个属性为每个实例是独立的,你必须明确地将其分配给对象和阴影原型财产; 就像你正在与做_objName
在你的代码性能。
但是,这是不是很漂亮,这个代码的性能要差很多。
如果你想它漂亮,它移动到构造函数(或使构造寻找类似的init
方法来调用,如果存在,那么你可以创建的原型,init方法。
为了使性能更好一点,你可以改变吸气功能
MyObj.prototype.getObj = function() {
var obj = {};
this.getObj = function(){ return obj; }; // overwrite itself
return obj;
};
但它仍然有函数调用的开销。 对于更优雅,你可以使用删除自身在第一次访问一个getter属性(在旧的浏览器不支持):
Object.defineProperty(MyObj.prototype, "objName", {
get: function() {
var obj = {};
Object.defineProperty(this, "objName", {
value: obj,
writable: true //?
});
return obj;
},
enumerable: true,
configurable: true
});
现在,你可以省略函数调用括号。
这意味着,在原型对象不继承它的拷贝,而是作为参考。
只要是明确的。 首先在JavaScript中的所有对象都通过引用传递,而不是价值。 只有原语是按值传递。 其次,你实际上并没有“复制”或“传递”任何东西。 当您设置一个prototype
,你要创建一个原型的链。 这意味着,在您的情况:
var MyObj = function() {};
MyObj.prototype.objName = {} ;
var o1 = new MyObj ();
var o2 = new MyObj ();
无论o1
和o2
没有叫任何财产objName
,你可以简单地测试它:
console.log(Object.keys(o1)); // []
当JS看到这样一个代码o1.objName
,作为第一件事情检查对象具有这个属性,如果有,使用它。 如果没有,开始寻找在原型车的链条,通过原型开始o1
,这是MyObj.prototype
:它发现性能objName
,并将其返回。 如果没有找到它,那么JS会继续检查原型MyObj.prototype
,等等。 所以,这里的要点: MyObj.prototype
它是一个对象:与您共享之间的物体o1
和o2
。 这就是为什么实例objName
是一样的。 这正是具有相同的逻辑:
function objName(obj) {
return "objName" in obj ? obj.objName : O.objName;
}
var O = { objName: [] };
var foo = {};
var bar = {};
objName(foo).push(0);
objName(bar).push(1);
所以,你不能把在prototype
是不是要跨对象共享使用原型创建的任何对象。 我要说的是共享状态一样,也是应该避免的一个不好的做法,这就是为什么在一般的prototype
应该不会有这样的属性。 它仍然是我不明白你为什么不能修改构造函数,但问题是:当你创建对象的实例,你要“建立”了。 通常情况下,调用构造函数,但是任何功能是好的。 这也让当你要支持继承,并呼吁“超级”构造函数初始化对象。