Pro javascript学习笔记之继承之三(prototypal inheritance)
2008-09-23 16:42 wlstyle 阅读(760) 评论(0) 收藏 举报原型继承(prototypal inheritance)
原型继承是一个很不同的继承方式,要很好的理解他我们需要抛弃所有你知道的关于类和实例的理解。只保留关于对象的概念。传统的创建一个对象的方法首先是通过类定义对象的结构,然后通过实例化这个类来创建一个新的对象。通过这种方式创建的对象拥有他们自己的由对象定义的属性的版本。还有一个连接到每个实例方法的单一副本(指对象定义中定义的方法);在原型继承中,我们简单地创建了一个对象,而不是通过类定义结构。定义的这个对象然后被新对象重用。由于原型链工作的方式,它被称作原型对象因为他为其他的对象提供了一个模板(为了和其他原型对象区别它以斜体表示)。下面我们来实现一个原型继承。
我们在这里定义了一个对象 而不是使用构造函数来定义类的结构。这是一个你想为任何和Person类似对象创建的一个原型对象。在这里面定义所有你想这些对象拥有的方法和属性。然后给他们赋予初始值。对于这些方法,这些初始值可能不会改变,而对于属性值,这些初始值肯定要被改变。
我们创建了一个和Person相类似的对象。通过使用Clone函数(这个将在下一部分仔细的考量这个函数),这个提供了一个带有原型属性的空对象指向原型对象。这意味着如果在该对象上没有找到任何的属性和方法,那么他将在原型对象中寻找属性和方法。为了创建Author,你不需要像以前那样创建Person的子类,而只需要使用clone函数。
这个clone出来的Author的属性和方法可以重写。你能改变Person对象给定的默认值,或者添加必要的属性和方法。这样就创建了一个新的原型对象这样就可以创建一个和Author类型的对象。
2
3 Author.books=[];//default values
4
5 Author.getBooks=function(){
6
7 return this.books;
8
9 };
10
1 不对称读写继承的成员(Asymmetrical Reading and Writing of Inherited Members)
我们提到为了有效的运用原型继承之前。我们必须忘掉一切传统继承方法。这是一个例子。在传统继承中,每一个Author的实例都有一个books数组的副本。你能通过author[1].books.push(‘what a good day’)这样来添加记录。这在最开始是不可能的如果使用原型继承,因为这是由于原型链的工作方式决定的。一个clone(比如clone(Author))不是一个完全独立的原型对象的副本。通过clone创建的是一个有原型属性的空对象,他指向prototypal objected。当他刚被创建的时候author[1].name实际上是一个链接到Person.name这个原始属性。这是因为固有的在原型链接中的读写的不对称性决定的。
当你读取author[1].name的时候,你是从原型的链接中得到值。这使你没有直接在author[1]这个实例中定义一个name属性。当你对author[1].name进行赋值时,这时候你给author[1]添加了一个新的属性name指向该对象。
下面这个例子说明了这个不对称性
这同样说明 我们为何要创建一个从引用中传递过来数据类型的副本。在上面的例子中添加到authorClone.books数组的一个新值实际上是添加到了Author..books中。这样非常的糟糕,因为你刚才改变的值不仅影响到Author这个对象而且影响到任何从Author继承的但还没后重写这个属性的对象。你必须在改变他们的对象创建所有数组和对象的副本。我们很容易遗忘这点而从新设置该原型对象(prototype object)。这种情况应该避免。调试这之中的类型错误需要大量的时间,在这种情况下,我们可以通过方法hasOwnprototype来区别是通过继承得到的成员,还是自己本省的成员。有些时候原型对象(prototype objects)拥有子对象。如果你像重写子对象中的一个值,那么你必须重新写整个对象。我们可以通过设置子对象为一个空对象 然后重新定义他来实现。但是如果这样cloned对象必须知道每个子对象的结构初始值。为了使对象之间尽量降低耦合度。任何复杂的子对象都要通过方法创建。
在这个例子中,chilidobject被重新创建compoundObjectClone.childObject.num也进行了设置,这里的问题是compoundObjectClone必须知childObject有两个属性。分别为true和10。最好的方式是通过一个工厂方法来创建childobject.
2 复制函数(thet clone Function)
2 function clone(object){
3 function F(){}
4 F.prototype= object;
5 return new F;
6 }
7
首先复制函数创建了一个空函数F,然后设置F函数的原型属性指向原型对象,这里可以看出javascript设计之出的意图,原型(prototype)属性指向原型对象,通过原型链他提供了一个到继承成员的链接,最后,函数通过new操作符创建了一个新的对象。这个被返回的复制对象是一个空对象,除了包含原型属性。这个属性直接指向原型对象,
浙公网安备 33010602011771号