防止构造函数的多个实例共享相同的原型属性
Preventing multiple instances of a constructor function from sharing the same prototype properties
正当我认为我掌握了JavaScript中原型继承的工作原理时,我遇到了一个我以前没有考虑过的问题。
请看下面的简单JavaScript代码:
var Observable = function () {
this.events = [];
};
Observable.prototype.addEvent = function (e) {
this.events.push(e);
};
var Model = function () {};
Model.prototype = new Observable();
var appModel = new Model();
var taskModel = new Model();
appModel.addEvent('Hello');
taskModel.addEvent('World');
查看appModel.events
或taskModel.events
都会得到相同的数组:['Hello', 'World']
。我要做的是让每个新的Model
有自己的events
数组尽可能干净的方式。Model
的工作原理如下:
var Model = function () {
this.events = [];
};
Model.prototype = new Observable();
然而,随着更多的属性被添加到Observable
,这变得更加笨拙。我想我可以这样修改:
var Model = function () {
this.prototype.constructor.apply(this, arguments);
};
Model.prototype = new Observable();
虽然我相信你们中有JavaScript经验的人意识到这会抛出一个错误:TypeError: Cannot read property 'constructor' of undefined
.
总之,我正在寻找一种方法,让每个新的Model
从Observable
继承属性,每个Model
都有自己的events
。我意识到这是非常类,但我想知道如何做到这一点,只使用基于JavaScript原型的继承。
值得注意的是,我看过Dean Edward的Base.js。以下作品:
var Observable = Base.extend({
constructor: function () {
this.events = [];
},
addEvent: function (e) {
this.events.push(e);
}
});
var Model = Observable.extend({
constructor: function () {
this.base();
}
});
var appModel = new Model();
var taskModel = new Model();
appModel.addEvent('Hello');
taskModel.addEvent('World');
但是下面的不:
var Observable = Base.extend({
events: [],
addEvent: function (e) {
this.events.push(e);
}
});
var Model = Observable.extend({
constructor: function () {
this.base();
}
});
var appModel = new Model();
var taskModel = new Model();
appModel.addEvent('Hello');
taskModel.addEvent('World');
除此之外,我还想学习如何使用不使用类库的JavaScript原型来做到这一点。
我在这里理解的是,您希望每个实例都有它们单独的事件数组,如果是这样,请遵循答案:
function Model(){
this.events = [];
this.addEvent = function(eventName){
this.events.push(eventName);
};
this.getEvents = function(){
return this.events;
}
}
var m1 = new Model;
var m2 = new Model;
m1.addEvent("eve-1");
m2.addEvent("eve-2");
m1.getEvents(); //["eve-1"]
m2.getEvents(); //["eve-2"]
在您的情况下,您直接将事件添加到prototype
而不是实例,因此它们被添加到所有实例中…我希望这对你有帮助
我曾尝试过这个来解决我的问题:
var Model = function () {
this.prototype.constructor.apply(this, arguments);
};
Model.prototype = new Observable();
实际的解决方案是这样做:
var Model = function () {
Model.prototype.constructor.apply(this, arguments);
};
Model.prototype = new Observable();
这将给每个Model
它自己的events
数组,以及给每个Model
Observable
构造函数创建的任何其他属性。这里的小开销是Model.prototype.events
是一个永远不会被访问的空数组。
这里的第一个代码位导致Model
的每个实例都有一个共同的events
数组的原因是因为它们对Observable
的单个公共实例有一个原型引用。换句话说,通过
Model.prototype = new Observable();
你基本上是告诉JavaScript"让Model
的所有实例都像这个特定的Observable
的实例"。
class
和extends
关键字。
class Observable {
constructor() {
this.events = [];
}
addEvent() {
this.events.push(e);
}
}
class Model extends Observable {
// Model definition
};
遗憾的是,对ECMAScript 6的支持仍然不是很好。ECMAScript 5添加了对象。(至少就我所知,)
var Observable = function () {
this.events = [];
};
Observable.prototype.addEvent = function (e) {
this.events.push(e);
};
var Model = function () {
Observable.call(this);
};
Model.prototype = Object.create(Observable.prototype);
MDN有一篇很好的关于JavaScript中使用这种技术的OOP的文章
- 附加到原型属性的Do函数没有闭包
- 日期原型属性
- JS构造函数的原型属性与其原型之间的区别
- 为什么函数对象的实例没有继承函数原型属性
- 为什么浏览器显示原型属性不同
- 为什么在Function.prototype上没有原型属性
- 函数的原型属性
- 原型继承和原型属性
- 在JavaScript中,函数的默认值是多少'的原型属性
- Chrome 不支持 Javascript 中的原型属性吗?
- 我应该在JavaScript中将什么连接到子原型属性
- 更新 JavaScript 中的原型属性
- 请解释有关 JavaScript 中的原型属性和函数构造函数的详细信息
- 为什么原型函数无法读取原型属性
- 与对象属性同名的原型属性
- 如何获取原型属性列表
- 构造函数中的方法与函数的原型属性之间的差异
- JavaScript 原型属性
- 函数对象__proto__和原型属性
- 未在自定义 OL3 控件的构造函数中定义的原型属性