您的位置:首页 > 移动开发

Prototype和call(apply)结合实现继承

2014-10-20 15:14 351 查看
<html>

<head>

<title>Test</title>

<script type="text/javascript">

function Test(a,b)

{

this.A = a;

this.B = b;

this.say = function(){

alert("Test-C");

}

}

Test.sum = function(a,b)

{

return new Test(this.A + a, this.B + b);

}

Test.prototype.update = function()

{

alert("Test-update");

}

function TestChild1(){

this.say = function(){

alert("TestChild1-C");

}

}

//TestChild1.prototype = new Test(2, 3);

TestChild1.prototype = new Test();

function TestChild2(a, b){

//Test.call(this, a ,b);

this.say = function(){

alert("TestChild2-C");

}

Test.call(this, a ,b);

}

TestChild2.prototype = new Test();

var test1 = new TestChild1();

test1.say();

test1.update();

var test2 = new TestChild2(1, 2);

test2.say();

test2.update();

</script>

</head>

<body>

<div id = "testPrototype">test</div>

</body>

</html>

上面的代码Test是父类,TestChild1和TestChild2是子类,test1和test2分别是TestChild1和TestChild2的实例。

一.带参数的prototype继承方法的问题

//TestChild1.prototype = new Test(2, 3);

TestChild1.prototype = new Test();

如果TestChild1通过上面一句继承Test的话,那么TestChild1的所有实例的A和B都是固定的2和3。

所以继承的时候,带有参数的构造函数一般通过call和apply来继承,比如TestChild2继承的Test的方法。

二.Test.call(this, a ,b)不同位置的意义

function TestChild2(a, b){

Test.call(this, a ,b); ----位置1

this.say = function(){

alert("TestChild2-C");

}

//Test.call(this, a ,b); ----位置2

}

Test.call(this, a ,b);放在位置1和位置2的区别是,位置1的话,先继承父类的say函数,子类里面的say函数会将父类的say函数覆盖,因为javascript是按照顺序执行的。位置2的话,则是先继承父类的say,子类会将父类的重写,一般是放在位置1。

三.二者结合的继承方法

function TestChild2(a, b){

//Test.call(this, a ,b);

this.say = function(){

alert("TestChild2-C");

}

Test.call(this, a ,b);

}

TestChild2.prototype = new Test();

var test2 = new TestChild2(1, 2);

test2.say();

test2.update();

再看TestChild2的继承方法,则是结合了call和prototype两者。

如果去掉TestChild2.prototype = new Test();的话,test2.update();是访问不到的,因为Test.call(this, a ,b);只继承了构造函数。

四.父类函数都写在构造函数里的缺点

父类的函数都写在构造函数里的缺点,比如这样的形式。

function Test(a,b)

{

this.A = a;

this.B = b;

this.say = function(){

alert("Test-C");

}

}

say方法,每次生成一个实例,都必须在内存中生成一次,这样既占用内存效率又低。

最好的方案是,让say方法在内存中只生成一次,所有的实例都指向那个内存地址。要解决这个问题所以要采用prototype,例如下面的形式。

Test.prototype.update = function()

{

alert("Test-update");

}

五. 总结

总结:通过call来调用父类带参构造函数,通过 子类.prototype=new 父类() 来继承父类的方法。如果子类想要覆盖父类的方法,可以用TestChild2.prototype.say = function(){}。

把不变的属性和方法定义在prototype上面。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: