use*_*994 12 javascript inheritance properties
我正在尝试使用通用的"List"类,它将具有:
然后创建将继承自'List'的子类
//Class 'List'
function List(){
this.Items = new Array();
this.Add = function(){ alert('please implement in object') }
}
//Class CDList - which inherits from 'List'
function CDList(){
this.Add = function(Artist){
this.Items.push(Artist)
}
}
CDList.prototype = new List();
CDList.prototype.constructor = CDList;
//Create a new CDList object
var myDiscs = new CDList();
myDiscs.Add('Jackson');
myDiscs.Count() <-- this should be 1
//Create a second CDList object
var myDiscs2 = new CDList();
myDiscs2.Add('Walt');
myDiscs2.Add('Disney');
myDiscs2.Count() <-- this should be 2
Run Code Online (Sandbox Code Playgroud)
..但这似乎为所有'CDList'实例创建了一个共享的'Items'列表.我需要以某种方式为每个'CDList'实例创建一个新的'Items'列表的继承实例.
我怎样才能做到这一点 ?
*我在本例中使用'Items'列表作为示例.我希望能够在我的子类中为任何类型的继承属性提供新实例 - 不一定是Array对象.
谢谢你们!
Nik*_*iko 15
只有一个数组,因为您只创建一个.此数组附加到"CDList"的原型,因此在所有实例之间共享.
要解决此问题:不要将其附加到原型,而是附加到实例.这只能在施工时完成:
// This is the constructor of the parent class!
function List() {
this.Items = new Array();
}
// Add methods to the prototype, not to the instance ("this")
List.prototype.Add = function() { alert('please implement in object'); };
// Constructor of the child
function CDList() {
List.call(this); // <-- "super();" equivalent = call the parent constructor
}
// "extends" equivalent = Set up the prototype chain
// Create a new, temporary function that has no other purpose than to create a
// new object which can be used as the prototype for "CDList". You don't want to
// call "new List();", because List is the constructor and should be called on
// construction time only. Linking the prototypes directly does not work either,
// since this would mean that overwriting a method in a child overwrites the
// method in the parents prototype = in all child classes.
var ctor = function() {};
ctor.prototype = List.prototype;
CDList.prototype = new ctor();
CDList.prototype.constructor = CDList;
// Overwrite actions
CDList.prototype.Add = function(Artist) {
this.Items.push(Artist);
};
Run Code Online (Sandbox Code Playgroud)
演示:http://jsfiddle.net/9xY2Y/1/
一般概念是:东西,每个实例必须有其自己的副本(如在这种情况下,"项目"阵列)做时,必须在施工时间,即创建并连接到"这个"(=实例)new List()或new CDList().可以跨实例共享的所有内容都可以附加到原型上.这实际上意味着像"添加"功能这样的属性只创建一次,然后由所有实例使用(导致原始问题的原因).
链接原型时,您不能直接链接它们(通常),例如:
CDList.prototype = List.prototype;
DVDList.prototype = List.prototype;
// Now add a new function to "CDList"
CDList.prototype.Foo = function() { alert('Hi'); };
Run Code Online (Sandbox Code Playgroud)
因为三个函数"List","CDList"和"DVDList"的原型直接相互链接,所以它们都指向一个原型对象,即List.prototype.所以,如果你添加一些东西CDList.prototype实际上添加到List.prototype- 这也是"DVDList"的原型.
var dvd = new DVDList();
dvd.Foo(); // <-- alerts "hi" (oops, that wasn't intended...)
Run Code Online (Sandbox Code Playgroud)
诀窍是将原型链接到父类的新实例:
CDList.prototype = new List();
Run Code Online (Sandbox Code Playgroud)
这将创建类型的新对象"名单()"用特定特征函数的原型"目录()"链接到新的对象,使您能够调用原型直接在物体上的属性:
var l = new List();
alert( l.hasOwnProperty("Add") ); // <-- yields "false" - the object l has no
// property "Add"
l.Add("foo"); // <-- works, because the prototype of "List" has a property "Add"
Run Code Online (Sandbox Code Playgroud)
但是,请记住,我们打算使用函数"List()"的主体在每个实例的基础上创建像这个数组"Items"的东西?它是您放置任何"构造函数"代码的地方,例如
function User(userId) {
$.getJSON('/user/' + userId, ...
}
function Admin() {}
Admin.prototype = new User( // ... now what?
Run Code Online (Sandbox Code Playgroud)
一个非常干净的解决方案是使用另一个函数来创建一个prototype-object:
var ctor = function() {}; // <-- does nothing, so its super safe
// to do "new ctor();"
Run Code Online (Sandbox Code Playgroud)
现在可以直接链接原型,因为我们永远不会添加任何东西ctor.prototype:
ctor.prototype = List.prototype;
Run Code Online (Sandbox Code Playgroud)
如果我们这样做:
CDList.prototype = new ctor();
Run Code Online (Sandbox Code Playgroud)
"CDList()"的原型成为"ctor"类型的新对象,它没有自己的属性,但可以扩展,例如通过新的"添加"功能:
CDList.prototype.Add = function() { /* CD specific code! */ };
Run Code Online (Sandbox Code Playgroud)
但是,如果你没有为这个新的原型对象添加"Add"属性,那么"ctor()"的原型就会启动 - 这就是"List()"的原型.这就是理想的行为.
此外,"List()"中的代码现在只在您执行new List()或直接从另一个函数(在子类中通过List.call(this);)调用时执行.
试试这个:
function CDList(){
List.call( this )
this.Add = function(Artist){
this.Items.push(Artist)
}
}
Run Code Online (Sandbox Code Playgroud)
你需要调用超级构造器...
我喜欢关于javascript继承的mdn网络的这篇文章.我尝试了这种方法/技术,它在我测试的所有浏览器(Chrome,Safari,IE8 +,FF)中都能正常工作.
| 归档时间: |
|
| 查看次数: |
7397 次 |
| 最近记录: |