第八章 8.4 原型和继承(Prototypes and Inheritance)

前面我们看到了如何使用 constructor 来初始化对象。如果这样做,那么每一个创建的新对象都会对那些相同的属性,方法建立一个独立的副本。而实际上有更加有效的方法来指定方法,常量,以及其他一些可被所有该类的对象共享的属性。

JavaScript 对象从一个原形对象(prototype object) 继承属性。所有对象都有原型;原型的所有属性看上去就像使用它作为原型的那些对象的属性一样。简单的说就是: 所有对象都从他的原型继承属性
(each object inherits properties from its prototype).

对象的 prototype 通过它的 constructor function 来定义。JavaScript 里所有的 function 都有一个 prototype 属性。这个属性开始是空的,接下来你给他添加的任何属性都会被 constructor 创建的对象所拥有。

prototype 对象和 constructor 相关联。这意味着 prototype 可以作为放置方法以及其他常量的理想场所。原型中的属性不会被复制到新创建的对象中去,他们的属性看上去就像对象的属性一样。这意味着,使用原型能够大幅度的减少多个同类对象占用的内存。

每一个 class 都只有一个 prototype object, 附带一套属性。但我们在运行时可能会创建多个类的实例。那么如果发生对原型的属性的读写会发生什么情况?
当你读一个属性的时候,JavaScript 首先尝试去查找对象本身是否有这个属性,如果没有,接着去查找原型里面是否有。有的话就返回结果。
而当你写原型的属性的时候,因为多个对象共享原型,显然是不能直接在原型上进行写操作的。这个时候实际上 JavaScript 会在对象上创建一个同名的属性,然后把值写到里面。当你下次读这个属性的时候,JavaScript 一下子就在对象的属性里查找到了,那么就不需要去原型里查找了。这个时候,我们说“对象的属性掩盖或隐藏了原型的属性”。(shadows or hides) 。

从上面讨论看出,其实我们在设计类的时候,只要掌握一个原则: 在原型里仅定义一些方法(方法一般是不会变的),常数,常量等。做到这一点就不容易混淆了。
例子:

None.gif //  Define a constructor method for our class.
None.gif//
 Use it to initialize properties that will be different for
None.gif//
 each individual Circle object.
None.gif
function  Circle(x, y, r)
None.gif{
None.gif    
this .x  =  x;   //  The X-coordinate of the center of the circle
None.gif
     this .y  =  y;   //  The Y-coordinate of the center of the circle
None.gif
     this .r  =  r;   //  The radius of the circle
None.gif
}
None.gif
None.gif
None.gif
//  Create and discard an initial Circle object.
None.gif//
 This forces the prototype object to be created in JavaScript 1.1.
None.gif
new  Circle( 0 , 0 , 0 );
None.gif
None.gif
None.gif
//  Define a constant: a property that will be shared by
None.gif//
 all circle objects. Actually, we could just use Math.PI,
None.gif//
 but we do it this way for the sake of instruction.
None.gif
Circle.prototype.pi  =   3.14159 ;
None.gif
None.gif
None.gif
//  Define a method to compute the circumference of the circle.
None.gif//
 First declare a function, then assign it to a prototype property.
None.gif//
 Note the use of the constant defined above.
None.gif
function  Circle_circumference(  ) {  return   2   *   this .pi  *   this .r; }
None.gifCircle.prototype.circumference 
=  Circle_circumference;
None.gif
None.gif
None.gif
//  Define another method. This time we use a function literal to define
None.gif//
 the function and assign it to a prototype property all in one step.
None.gif
Circle.prototype.area  =   function (  ) {  return   this .pi  *   this .r  *   this .r; }
None.gif
None.gif
None.gif
//  The Circle class is defined.
None.gif//
 Now we can create an instance and invoke its methods.
None.gif
var  c  =   new  Circle( 0.0 0.0 1.0 );
None.gif
var  a  =  c.area(  );
None.gif
var  p  =  c.circumference(  );

内置的类的 prototype.

不光是用户自定义的类可以有 prototype. 系统内置的类比如 String, Date 也都有的。而且你可以向他们添加新的方法,属性等。
下面这段代码就对所有的 String 对象添加了一个有用的函数:

None.gif //  Returns true if the last character is c
None.gif
String.prototype.endsWith  =   function (c) {
None.gif    
return  (c  ==   this .charAt( this .length - 1 ))
None.gif}

然后我们就可以类似这样的来调用了:

None.gif var  message  =   " hello world " ;
None.gifmessage.endsWith('h')  
//  Returns false
None.gif
message.endsWith('d')   //  Returns true
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值