JavaScript:原型和继承(上篇)
2013-06-09 18:59
218 查看
我们已经知道,方法就是作为对象的一个属性来调用的一个函数。当一个函数按照这种方式被调用,用来访问这个函数的对象就变成了this关键字的值。假设想要计算一个Rectangle对象所代表的矩形的面积,可以这么做:
可是这是一种解决方案。它证明了每个JavaScript对象都包含着对另一个对象(也就是它的原型对象)的内部引用。原型对象的任何属性,表现为每个以它为原型的对象的属性。这句话的另一种表达方式就是,JavaScript对象从它的原型那里继承属性。
我们已经知道,用new运算符可以创建一个新的空对象,然后把构造函数作为这个对象的一个方法来调用。可是这并非事情的全部,在创建了这个空对象以后,new设置了这个对象的原型。
一个对象的原型就是它的构造函数的prototype属性的值。所有的函数都有一个prototype属性,当这个函数被定义的时候,prototype属性自动创建和初始化。prototype属性的初始化值是一个对象,这个对象只带有一个属性。这个属性名为constructor,它指回到和原型相关联的那个构造函数。(XxxFunction.prototype.constructor==XxxFunction)添加给这个原型对象的任何属性,都会成为被构造函数所初始化的对象的属性。
用一个例子来说明更清楚些。下面,再次用到Rectangle( )构造函数:
构造函数为对象的“类”提供一个名字并初始化width和height这样的属性,这些属性可能在类的每个实例中都不同。原型对象和这个构造函数相关,并且,构造函数初始化的每个对象都确实从原型那里继承了完全相同的一组属性。这意味着,原型对象是放置方法和其他不变属性的理想地方。
注意,继承作为查找一个属性值的过程的一部分自动发生。属性并非从原型对象复制到新对象,它们只是像那些对象的属性一样地出现。这有两个重要的含义:
① 首先,使用原型对象可以显著地减少每个对象所需的内存,因为对象可以继承原型的很多属性。
② 即便是在对象创建以后才添加到原型中的属性,对象也可以继承它。这意味着,可以为已有的类添加新方法。
继承的属性就好像对象的常规属性一样发挥作用。可以用for/in循环来枚举它们,并在in运算符中测试它们。只能用Object.hasOwnProperty( )来区分继承的属性和常规的属性。
function computeAreaOfRectangle(r){ return r.width*r.height; }这也有效,但是并不面向对象。在使用对象的时候,最好在对象上调用方法,而不是将对象传递给一个函数。也就是这么做:
var r=new Rectangle(8.5,11); r.area=function(){ return this.width*this.height; } var a=r.area();在调用一个方法前必须为对象添加这个方法。当然这里的方法很可笑。可以在构造函数中初始化area属性使其指向一个面积计算函数,这样就可以改善这种状况了。下面是改进后的Rectangle()构造函数:
function Rectangle(w,h){ this.width=width; this.height=h; this.area=function(){ return this.width*this.height; } }使用这个新的构造函数,我们就可以编写这样的代码:
var r=new Rectangle(8.5,11); var a=r.area();这个解决方案很有效,但还不是最优的。创建的每个矩形都有三个属性。每个矩形的width属性和height属性可能都不同,但是每个Rectangle对象的area属性总是指向同一个函数。针对有意让同一个类的所有对象共享的方法来使用一个常规的属性,这样做的效率是很低的。
可是这是一种解决方案。它证明了每个JavaScript对象都包含着对另一个对象(也就是它的原型对象)的内部引用。原型对象的任何属性,表现为每个以它为原型的对象的属性。这句话的另一种表达方式就是,JavaScript对象从它的原型那里继承属性。
我们已经知道,用new运算符可以创建一个新的空对象,然后把构造函数作为这个对象的一个方法来调用。可是这并非事情的全部,在创建了这个空对象以后,new设置了这个对象的原型。
一个对象的原型就是它的构造函数的prototype属性的值。所有的函数都有一个prototype属性,当这个函数被定义的时候,prototype属性自动创建和初始化。prototype属性的初始化值是一个对象,这个对象只带有一个属性。这个属性名为constructor,它指回到和原型相关联的那个构造函数。(XxxFunction.prototype.constructor==XxxFunction)添加给这个原型对象的任何属性,都会成为被构造函数所初始化的对象的属性。
用一个例子来说明更清楚些。下面,再次用到Rectangle( )构造函数:
function Rectangle(w,h){ this.width=w; this.height=h; } Rectangle.prototype.area=function(){ return this.width*this.height; }
构造函数为对象的“类”提供一个名字并初始化width和height这样的属性,这些属性可能在类的每个实例中都不同。原型对象和这个构造函数相关,并且,构造函数初始化的每个对象都确实从原型那里继承了完全相同的一组属性。这意味着,原型对象是放置方法和其他不变属性的理想地方。
<html> <head> <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> </head> <body> <script> String.prototype.say=function(message){ return message; } </script> <a href="javascript:'tom'.say('hello');">test</a> </body> </html>
注意,继承作为查找一个属性值的过程的一部分自动发生。属性并非从原型对象复制到新对象,它们只是像那些对象的属性一样地出现。这有两个重要的含义:
① 首先,使用原型对象可以显著地减少每个对象所需的内存,因为对象可以继承原型的很多属性。
② 即便是在对象创建以后才添加到原型中的属性,对象也可以继承它。这意味着,可以为已有的类添加新方法。
继承的属性就好像对象的常规属性一样发挥作用。可以用for/in循环来枚举它们,并在in运算符中测试它们。只能用Object.hasOwnProperty( )来区分继承的属性和常规的属性。
var r=new Rectangle(2,3); r.hasOwnProperty("width"); //true r.hasOwnProperty("area"); //false "area" in r; //true
相关文章推荐
- javascript 原型继承
- JS学习笔记——JavaScript继承的6种方法(原型链、借用构造函数、组合、原型式、寄生式、寄生组合式)
- JavaScript原型继承之基础机制分析
- JavaScript原型和继承
- 理解Javascript_05_原型继承原理
- 浅谈javascript的原型继承
- node.js javascript理解原型继承
- javascript中的原型继承
- 基于JavaScript实现继承机制之原型链(prototype chaining)的详解
- javascript原型继承工作原理和实例详解
- JavaScript继承基础讲解,原型链、借用构造函数、混合模式、原型式继承、寄生式继承、寄生组合式继承
- 深入理解javascript原型和闭包(6)——继承
- JavaScript原型、函数伪装(apply,call)、继承
- JavaScript 原型 继承
- 再谈Javascript原型继承
- Javascript 原型和继承(Prototypes and Inheritance)
- JavaScript中继承(一)-- 原型链
- JavaScript中的原型继承
- 再谈Javascript原型继承
- JavaScript 利用原型和原型链实现对象继承