`
hduyou
  • 浏览: 23398 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
最近访客 更多访客>>
社区版块
存档分类
最新评论

js 的prototype相关知识(转载)

阅读更多
最基本的用法 把ClassA的一个实例赋值给ClassB,
ClassB就继承了ClassA的所有属性。
代码入下:

 
function ClassA()  
{  
    this.a='a';  
}  
function ClassB()  
{  
    this.b='b';  
}  
ClassB.prototype=new ClassA();  
var objB=new ClassB();  
for(var p in objB)document.write(p+"
");  



从原型继承理论的角度去考虑,
js的原型继承是引用原型,不是复制原型,
所以,修改原型会导致所有B的实例的变化。
代码如下:

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




然而 子类对象的写操作只访问子类对象中成员,
它们之间不会互相影响,因此,
写是写子类 读是读原型(如果子类中没有的话)。


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





每个子类对象都执有同一个原型的引用,
所以子类对象中的原型成员实际是同一个。



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




构造子类时 原型的构造函数不会被执行


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();  




接下来是致命的,在子类对象中访问原型的成员对象:

function ClassA()  
{  
    this.a=[];  
}  
function ClassB()  
{  
    this.b=function(){alert();};  
}  
ClassB.prototype=new ClassA();  
var objB1=new ClassB();  
var objB2=new ClassB();  
objB1.a.push(1,2,3);  
alert(objB2.a);  
//所有b的实例中的a成员全都变了!!


所以 在prototype继承中 原型类中不能有成员对象! 所有成员必须是值类型数据(string也可以)
用prototype继承有执行效率高,不会浪费内存,为父类动态添置方法后子类中马上可见等的优点。

prototype继承是通过把子类的原型对象(prototype)设置成父类的一个实例来进行继承的。

prototype继承也有四个比较明显的缺点:
  缺点一:父类的构造函数不是像JAVA中那样在给子类进行实例化时执行的,而是在设置继承的时候执行的,并且只执行一次。这往往不是我们希望的,特别是父类的构造函数中有一些特殊操作的情况下。
  缺点二:由于父类的构造函数不是在子类进行实例化时执行,在父类的构造函数中设置的成员变量到了子类中就成了所有实例对象公有的公共变量。由于JavaScript中继承只发生在“获取”属性的值时,对于属性的值是String,Number和Boolean这些数据本身不能被修改的类型时没有什么影响。但是Array和Object类型就会有问题。
  缺点三:如果父类的构造函数需要参数,我们就没有办法了。
  缺点四:子类原本的原型对象被替换了,子类本身的constructor属性就没有了。在类的实例取它的constructor属性时,取得的是从父类中继承的constructor属性,从而constructor的值是父类而不是子类。

可以针对prototype的缺点进行改造
比如把它写成Function对象的一个方法,这样用的时候方便。

Function.prototype.Extends = function (parentClass)
{
var Bs = new Function();
Bs.prototype = parentClass.prototype;
this.prototype = new Bs();
this.prototype.Super = parentClass;
this.prototype.constructor = this;
}



//针对第3,6个
<script> 
function ClassA() 
{ 
    this.a=[] 
    this.aa=100; 
} 


function ClassB() 
{ 
    this.b=function(){return "classbb"}; 
} 




ClassB.prototype=new ClassA(); 



var objB1=new ClassB(); 
var objB2=new ClassB(); 



objB1.a.push(1,2,3); 
objB1.aa=10100 
alert(objB2.a); 
alert(objB2.aa); 
</script>

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics