js是门灵活的语言,实现一种功能往往有多种做法,ECMAScript没有明确的继承机制,而是通过模仿实现的,根据js语言的本身的特性,js实现继承有以下通用的几种方式
1.使用对象冒充实现继承(该种实现方式可以实现多继承)
实现原理:让父类的构造函数成为子类的方法,然后调用该子类的方法,通过this关键字给所有的属性和方法赋值
1. function
2. {
3. this.fname=firstname;
4. this.age=40;
5. this.sayAge=function()
6. {
7. this.age);
8. }
9. }
10. function
11. {
12. this.parent=Parent;
13. this.parent(firstname);
14. delete this.parent;
15. this.saySomeThing=function()
16. {
17. this.fname);
18. this.sayAge();
19. }
20. }
21. var mychild=new Child("李");
22. mychild.saySomeThing();
2.采用call方法改变函数上下文实现继承(该种方式不能继承原型链,若想继承原型链,则采用5混合模式)
实现原理:改变函数内部的函数上下文this,使它指向传入函数的具体对象
1. function
2. {
3. this.fname=firstname;
4. this.age=40;
5. this.sayAge=function()
6. {
7. this.age);
8. }
9. }
10. function
11. {
12.
13. this.saySomeThing=function()
14. {
15. this.fname);
16. this.sayAge();
17. }
18. this.getName=function()
19. {
20. return
21. }
22.
23. }
24. var child=new Child("张");
25. Parent.call(child,child.getName());
26. child.saySomeThing();
3.采用Apply方法改变函数上下文实现继承(该种方式不能继承原型链,若想继承原型链,则采用5混合模式)
实现原理:改变函数内部的函数上下文this,使它指向传入函数的具体对象
1. function
2. {
3. this.fname=firstname;
4. this.age=40;
5. this.sayAge=function()
6. {
7. this.age);
8. }
9. }
10. function
11. {
12.
13. this.saySomeThing=function()
14. {
15. this.fname);
16. this.sayAge();
17. }
18. this.getName=function()
19. {
20. return
21. }
22.
23. }
24. var child=new Child("张");
25. Parent.apply(child,[child.getName()]);
26. child.saySomeThing();
4.采用原型链的方式实现继承
实现原理:使子类原型对象指向父类的实例以实现继承,即重写类的原型,弊端是不能直接实现多继承
1. function
2. {
3.
4. this.sayAge=function()
5. {
6. this.age);
7. }
8. }
9. function
10. {
11. this.fname=firstname;
12. this.age=40;
13. this.saySomeThing=function()
14. {
15. this.fname);
16. this.sayAge();
17. }
18. }
19.
20. Child.prototype=new
21. var child=new Child("张");
22. child.saySomeThing();
原型链的问题:
虽然很强大,可以用它来实现继承,但它也存在一些问题。最主要的问题来自包含引用类型值的原型。在通过原型来实现继承时,原型实际上会变成一个类型的实例。于是,原先的实例属性也顺理成章的变成了现在的原型的属性了。看例子吧!
function SuperType() {
this.colors = ["red", "green", "blue"];
}
function SubType() {
}
//继承了SuperType
SubType.prototype = new SuperType();
var instance1 = new SubType();
instance1.colors.push("black");
alert(instance1.colors); //red,green,blue,black
var instance2 = new SubType();
alert(instance2.colors); //red,green,blue,black
SuperType构造函数定义了一个属性,该属性包含一个数组(引用类型值)。当SubType通过原型继承了SuperType之后,SubType.prototype就变成了SuperType的一个实例。因此也拥有了SuperType的所有属性和方法。结果SubType会共享这个colors属性,我们通过对instance1.colors的修改,能够通过instance2.colors反映出来。
第二个问题是创建子类型的实例时,不能向超类型的构造函数中传递函数。鉴于这几点问题,实践中很少会单独使用原型链。
5.采用混合模式实现继承
1. function
2. {
3.
4. this.sayAge=function()
5. {
6. this.age);
7. }
8. }
9.
10. Parent.prototype.sayParent=function()
11. {
12. "this is parentmethod!!!");
13. }
14.
15. function
16. {
17. this);
18. this.fname=firstname;
19. this.age=40;
20. this.saySomeThing=function()
21. {
22. this.fname);
23. this.sayAge();
24. }
25. }
26.
27. Child.prototype=new
28. var child=new Child("张");
29. child.saySomeThing();
30. child.sayParent();