JavaScript面向对象的程序设计2(组合构造和原型 继承)

来源:互联网 发布:电脑不能从网络启动 编辑:程序博客网 时间:2024/05/16 02:06

1.组合使用构造函数模式和原型模式

构造函数:定义实例属性
原型模式:定义方法和共享属性

function Person(name, age, job) {            this.name=name;            this.age=age;            this.job=job;            this.friends=["Curry","Green"];        }        Person.prototype={            constructor:Person,            sayName:function () {                alert(this.name);            }        }        var person1=new Person("Nicholas",29,"software engineer");        var person2=new Person("Grey",24,"Doctor");        person1.friends.push("Thompson");        alert(person1.friends);//"Curry,Green,Thompson"        alert(person2.friends);//"Curry,Green"        alert(person1.friends==person2.friends);//false        alert(person1.sayName==person2.sayName);//true

2.继承

基本思想:让原型对象=另一个类型的实例
结果:该原型对象包含一个指向另一个原型的指针[[Prototype]]

  • 原型
    这里写图片描述

  • 原型链(很少单独使用)

function SuperType(){            this.property=true;        }        SuperType.prototype.getSuperValue=function(){            return this.property;        };        function SubType(){            this.subproperty=false;        }        //继承列SuperType        SubType.prototype=new SuperType();        SubType.prototype={            getSubValue:function(){                return this.subproperty;            },            someOtherMethod:function(){                return false;            }        };        var instance=new SubType();        alert(instance.getSuperValue());//true

这里写图片描述

上面的instance.getSuperValue()会经历三个步骤:
(1)搜索实例;
(2)搜索SubType.prototype;
(3)搜索SuperType.prototype.

  • 别忘记默认的原型
    事实上, 前面例子中展示的原型链还少一环。我们知道,所有引用类型默认都继承了Object ,而
    这个继承也是通过原型链实现的。记住, 所有函数的默认原型都是Objec t 的实例,因此默认原
    型都会包含一个内部指针,指向Object.prototype
    这里写图片描述

SubType继承了SuperType,SuperType继承了Object。
调用instance.toString()时,实际调用的是Object.prototype中的那个方法。

原型链存在的问题 :
(1)包含引用类型的值的原型,也就是引用类型的值会共享

function SuperType( ) {    this.colors = ["red",'blue","green"];    }function SubType( ) {    }    //继承了SuperType    SubType.prototype=new SuperType();    var instance1 = new SubType();    instance1.colors.push("black");    alert(instancel.colors);//red , blue,green,black"    var instance2 = new SubType();    alert(instance2.colors);//"red,blue, green,black"

(2)在创建子类型的实例时,不能向超类型的构造函数中传递参数。

  • 借用构造函数(很少用)
    基本思想:在子类型构造函数的内部调用超类型构造函数
function SuperType( ) {    this.colors = ["red",'blue","green"];    }function SubType( ) {    //继承了SuperType    SuperType.call(this);//注意    }    var instance1 = new SubType();    instance1.colors.push("black");    alert(instancel.colors);//red , blue,green,black"    var instance2 = new SubType();    alert(instance2.colors);//"red,blue, green"

借用构造函数的优势

function SuperType(name) {    this.name=name;    }function SubType( ) {    //继承了SuperType,同时传递参数    SuperType.call(this,"NIcholas");//实际是为了Subtype实例设置了name属性    this.age=29;//实例属性    }    var instance = new SubType();    instance1.colors.push("black");    alert(instance.name);//"Nicholas"    alert(instance.age);//29
  • 组合继承又称伪经典继承(最常用)

    将原型链和借用构造函数的技术组合在一块
    原型链:实现对原型属性和方法复用
    构造函数:实现对实例属性的继承

function SuperType(name) {    this.name=name;    this.colors=["red","blue","green"];}    SuperType.prototype.sayName=function(){        alert(this.name);    };function SubType( ) {    //继承属性    SuperType.call(this,name);    this.age=29;    //继承方法    SubType.prototype=new SuperType();    SubType.prototype.constructor=SubType;    SubType.prototype.sayAge=function(){        alert(this.age);    }    var instance1=new SubType("Nicholas",29);    instance1.colors.push("black");    alert(instance1.colors);//"red,blue,green,black"    instance1.sayName();//"Nicholas"    instande1.sayAge();//29var instance2=new SubType("Grey",27);    alert(instance2.colors);//"red,blue,green"    instance2.sayName();//"Gray"    instande2.sayAge();//27

SuperType 构造函数定义了两个属性: name 和colorso。SuperType的原型定义了一个方法sayName ( )。SubType 构造函数在调用SuperType 构造函数时传入了name 参数,紧接着又定义了它自己的属性age。然后,将SuperType 的实例赋值给SubType 的原型.然后又在该新原型上定义了方法 sayAge () 。这样一来,就可以让两个不同的SubType 实例既分别拥有自己属性一一包括colors 属性,又可以使用相同的方法了。

阅读全文
0 0