25javascript的prototype

来源:互联网 发布:莱斯特大学怎么样 知乎 编辑:程序博客网 时间:2024/05/01 05:30
javaScript是通过一种链接机制来支持继承,而不是通过完全面向对象语言所支持的基于类的继承模型。
每个javaScript对象都一个内置属性名为prototype,通过.prototype属性可以返回对象类型原型的引用。javascript为每一个类型(Type)都提供了一个prototype属性,将这个属性指向一个对象,这个对象就成为这个类型的"原型",这意味着由这个类型所创建的所有对象都具有这个原型的特性。
 
当通过点记法引用对象的一个函数或属性时,倘若对象上没有这个函数或属性,此时就会使用对象的prototype属性。当出现这种情况时,将检查对象的prototype属性所引用的对象。查看是否有所请求的属性或函数。如果prototype属性引用的对象也没有所需要的函数或属性,则会进一步检查这个对象(prototype属性引用的对象)的prototype属性,一次沿着链向上查找,直到找到所请求的函数或属性。如果已经达到链尾还没有找到,则返回undefined。


prototype机制是动态的,可以根据需要在运行时配置,而无需重新编译。你可以只在需要时向对象增加属性和函数,而且能动态地把单独的函数合并在一起。
1prototype动态的添加属性
在Javascript中,object就是一个associative array。一个function就是一个类。当你编写如下function时,其实就是定义了一个类,该function就是它的构造函数。


function MyObject(name, size)


       {


              this.name = name;


              this.size = size;


       }


之后,你可以方便的通过MyObject类的prototype属性来方便的扩充它。比如,你可以给他添加其他的属性和方法。
//给MyObject的原型扩展方法tellSize
       MyObject.prototype.tellSize = function()


       {


              return "size of "+this.name+" is "+this.size;


       }
//给MyObject的原型扩展属性color
       MyObject.prototype.color = "red";


       MyObject.prototype.tellColor = function()


       {


              return "color of "+this.name+" is "+this.color;


       }




       var myobj1 = new MyObject("tiddles", "7.5 meters");


       domDiv.innerHTML += myobj1.tellColor()+"<br /><br />";


你可以想象,当你调用tellColor()方法后,结果是这样的:
color of tiddles is red


很方便的是,prototype属性可以动态添加。比如,你需要往MyObject中加入一个height属性,并希望其提供一个tellHeight()方法来获得height属性的值。你可以在上面的代码后,继续添加如下的代码:
       MyObject.prototype.height = "2.26 meters";


       MyObject.prototype.tellHeight = function()


       {


              return "height of "+this.name+" is "+this.height;


       }


之后,你可以访问一下myobj1的tellHeight()方法,你可以得到如下的结果:
height of tiddles is 2.26 meters


2prototype的继承
基本的用法 把ClassA的一个实例赋值给ClassB ClassB就继承了ClassA的所有属性
<script>
function ClassA()
{
    this.a='a';
}
function ClassB()
{
    this.b='b';
}
ClassB.prototype=new ClassA();
var objB=new ClassB();
//打印出objB对象的所有属性名称
for(var p in objB)document.write(p+"<br>");
</script>




从原型继承理论的角度去考虑 js的原型继承是引用原型 不是复制原型
所以 修改原型会导致所有B的实例的变化
<script>
function ClassA()
{
    this.a='a';
}
function ClassB()
{
    this.b='b';
}
ClassB.prototype=new ClassA();
var objB=new ClassB();
alert(objB.a);
ClassB.prototype.a='changed!!';
alert(objB.a);
</script>




然而 子类对象的写操作只访问子类对象中成员 它们之间不会互相影响
因此 写是写子类 读是读原型(如果子类中没有的话)
<script>
function ClassA()
{
    this.a='a';
}
function ClassB()
{
    this.b='b';
}
ClassB.prototype=new ClassA();
var objB1=new ClassB();
var objB2=new ClassB();
objB1.a='!!!';
alert(objB1.a);
alert(objB2.a);
</script>




每个子类对象都执有同一个原型的引用 所以子类对象中的原型成员实际是同一个
<script>
function ClassA()
{
    this.a=function(){alert();};
}
function ClassB()
{
    this.b=function(){alert();};
}
ClassB.prototype=new ClassA();
var objB1=new ClassB();
var objB2=new ClassB();
alert(objB1.a==objB2.a);
alert(objB1.b==objB2.b);
</script>


构造子类时 原型的构造函数不会被执行
<script>
function ClassA()
{
    alert("a");
    this.a=function(){alert();};
}
function ClassB()
{
    alert("b");
    this.b=function(){alert();};
}
ClassB.prototype=new ClassA();
var objB1=new ClassB();
var objB2=new ClassB();
</script>

0 0