Javascript属性继承 [英] Javascript property inheritance

查看:73
本文介绍了Javascript属性继承的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用通用的List类,它将具有:

I'm trying to have a generic 'List' class, which will have:


  • 属性:项目 - 这将是一个'what-ever'的数组

  • 方法:Add() - 这是抽象的并由特定的'List'对象实现

  • 方法: Count() - 返回'items'的数量

然后创建将继承自'List'的子类

and then create sub-classes which will inherit from '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

..但是这个似乎为所有'CDList'实例创建了一个共享的'Items'列表。我需要以某种方式为每个'CDList'实例创建一个新的'Items'列表的继承实例。

..but this seems to create a shared 'Items' list for all 'CDList' instances. I need to somehow have a new inherited instance of the 'Items' list for each 'CDList' instance.

我该怎么做?

*我在这个例子中使用'Items'列表作为例子。我希望能够在我的子类中为任何类型的继承属性创建一个新实例 - 不一定是一个Array对象。

*I'm using in this example the 'Items' list as an example. I'd like to be able to have in my sub-classes a new instance for any type of inherited property - not necessarily an Array object.

感谢adv们!

推荐答案

只有一个数组,因为你只创建了一个数组。这个数组附加到CDList的原型,因此在所有实例之间共享。

There is only one Array because you only create one. This array is attached to the prototype of "CDList" and therefore shared between all instances.

要解决这个问题:不要将它附加到原型,而是附加到实例。这只能在施工时完成:

To solve this problem: don't attach it to the prototype, but to the instance. This can only be done at construction time:

// 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);
};

演示: http://jsfiddle.net/9xY2Y/1/

一般概念是:必须创建每个实例必须拥有自己的副本(在本例中为Items数组),并在构造时将其附加到this(=实例),即在执行时new List() new CDList()。可以跨实例共享的所有内容都可以附加到原型上。这实际上意味着像添加函数这样的属性只创建一次,然后由所有实例使用(导致原始问题的原因)。

The general concept is: Stuff that each instance must have its own copy of (like the "Items" array in this case) must be created and attached to "this" (= the instance) at construction time, i.e. when doing new List() or new CDList(). Everything that can be shared across instances can be attached to the prototype. This essentially means that properties like the "Add" function are created exactly one time and are then used by all instances (what caused the original issue).

链接原型时,你不能直接链接它们(通常),例如:

When linking prototypes, you must not directly link them (usually), e.g.:

CDList.prototype = List.prototype;
DVDList.prototype = List.prototype;

// Now add a new function to "CDList"
CDList.prototype.Foo = function() { alert('Hi'); };

因为三个函数List,CDList和DVDList的原型直接链接相互之间,它们都指向一个原型对象,即 List.prototype 。所以,如果你向 CDList.prototype 添加一些内容,你实际上将它添加到 List.prototype - 这也是原型DVDList。

Because the prototypes of the three functions "List", "CDList" and "DVDList" got directly linked to each other, they all point to one prototype object, and that is List.prototype. So, if you add something to CDList.prototype you actually add it to List.prototype - which also is the prototype of "DVDList".

var dvd = new DVDList();
dvd.Foo(); // <-- alerts "hi" (oops, that wasn't intended...)

诀窍是将原型链接到父类的新实例:

What does the trick is to link the prototype to a new instance of the parent class:

CDList.prototype = new List();

这会创建一个类型为List()的新对象,其特殊功能是原型函数List()链接到新对象,使您可以直接在对象上调用原型的属性:

This creates a new object of type "List()" with the special feature that the prototype of the function "List()" is linked to the new object, enabling you to call properties of the prototype directly on the object:

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"

但是,请记住,我们打算使用函数List()的主体在每个实例的基础上创建像这个数组Items的东西?它是您放置任何构造函数代码的地方,例如

However, remember that we intended to use the body of the function "List()" to create stuff like this array "Items" on a per-instance basis? It is the place where you put any "constructor" code, e.g.

function User(userId) {
    $.getJSON('/user/' + userId, ...
}

function Admin() {}
Admin.prototype = new User( // ... now what?

一个非常干净的解决方案是使用另一个函数来创建一个prototype-object:

One very clean solution is to use another function to create a prototype-object:

var ctor = function() {}; // <-- does nothing, so its super safe
                          // to do "new ctor();"

现在可以直接链接原型,因为我们永远不会将任何内容添加到 ctor.prototype

It is now okay to directly link the prototypes, because we will never add anything to ctor.prototype:

ctor.prototype = List.prototype;

如果我们这样做:

CDList.prototype = new ctor();

原型CDList()成为ctor类型的新对象,它没有自己的属性但可以扩展,例如通过新的添加功能:

the prototype of "CDList()" becomes a new object of type "ctor", that has no own properties but can be extended, e.g. by a new "Add" function:

CDList.prototype.Add = function() { /* CD specific code! */ };

但是,如果你没有为这个新的原型对象添加Add属性,那么原型ctor()开始 - 这是List()的原型。这就是所期望的行为。

However, if you do not add an "Add" property to this new prototype object, the prototype of "ctor()" kicks in - which is the prototype of "List()". And that's the desired behavior.

此外,List()中的代码现在只在你执行 new List()时执行或直接从另一个函数调用它(在子类中通过 List.call(this); )。

Also, the code in "List()" is now only executed whenever you do new List() or when you call it directly from another function (in a child class via List.call(this);).

这篇关于Javascript属性继承的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆