JavaScript学习3:原型和继承

        原型

        我们创建的每一个函数都有一个prototype(原型)属性,这个属性是一个对象,它的用途是包含可以由特定类型的所有实例共享的属性和方法。逻辑上可以这么理解:prototype是通过调用构造函数而创建的那个对象的原型对象。

        为什么要引入原型的概念呢?使用原型的目的,也是他的好处是可以让所有的对象实例共享它所包含的属性和方法。换句话说,就是不必再构造函数中定义对象信息,而是可以直接将这些信息添加到原型中。

        具体怎么用,我们来看代码实例:   

<span style="font-size:18px;">//原型实例
function Person(){}   //声明一个构造函数

Person.prototype.name='Lian';   //在原型里添加属性
Person.prototype.age=100;
Person.prototype.run=function(){    //在原型里添加方法
	return this.name + this.age + '奋斗中……';
};

var person1=new Person();
var person2=new Person();
alert(person1.run==person2.run);   //返回true,说明方法的引用地址是一致的,即两个对象共享了一个方法</span>

        为了更好的理解构造函数的声明方式和原型模式的声明方式的区别,我找了两张图分享给大家,帮助大家理解:

        

        我们从图中可以看到,在原型模式声明中,多了两个属性,这两个属性都是创建对象时自动生成的。_proto_属性是实例指向原型对象的一个指针,它的作用就是指向构造函数的原型属性constructor。通过这两个属性,就可以访问到原型里的属相和方法了。

        看到这里你会觉得奇怪,上面代码实例中的构造函数的函数体中什么也没有,才能访问到原型对象里的值,如果函数体中有属性或者方法呢?这里就要涉及一个原型模式执行流程的问题了:是先去查找构造函数实例里面的属性和方法,如果有,立刻返回,若没有,则去它的原型对象中找,若有,则返回。

        使用原型模式创建对象也有其缺点,那就是它省略了构造函数传参初始化这一过程,带来的缺点就是初始化的值都是一样的,但是这恰恰是它最大的优点,那就是共享。

        继承

        继承是面向对象中的一个核心概念,在比较正统的面向对象的语言中一般都会采用两种方式实现继承:一个是接口实现,一个是类继承。而我们的JavaScript只支持继承,而不支持接口实现,继承是如何实现的,这里要引入原型链的概念了。什么是原形链,我们看一段代码就会知道。

<span style="font-size:18px;">//继承实例
function A(){
	this.name ='Lian';
}

function B(){
	this.age=100;
}

function C(){
	this.address='中国';
}
B.prototype.age =200;
B.prototype =new A();  //B继承了A

C.prototype =new B();  //C又继承了B

var c=new C();
alert(c.name+' '+ c.age);  //C具有了A和B的属性</span>

        在JavaScript中,被继承的函数称为超类型(也就是面向对象中说的父类或者说是基类),继承的函数称为子类型(即子类或者派生类)。继承有好处,但是也有其自己的问题,比如字面量重写原型会中断关系,使用引用类型的原型,并且子类型无法给超类型传递参数。

        综合考虑,我们使用原形链加上构造函数,这样产生了组合继承。      

<span style="font-size:18px;">//组合继承
function Box(age){
	this.name='Lee';
	this.age=age;
}

Box.prototype.run=function(){
	return this.name +this.age;
};

function Desk(age ){
	Box.call(this,age);   //对象冒充,给超类型传参
}

Desk.prototype =new Box();   //原形链继承

var desk =new Desk(100);
alert (desk.run());   //显然Desk继承了Box的run方法</span>

        组合继承是JavaScript最常用的继承方式,但是,组合继承也有一点问题,那就是超类型在使用过程中会被调用两次,一次是创建子类型的时候,一次是在子类型构造函数的内部。这样会带来性能上的开销,如何解决?留给读者去思考……

评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值