您的位置:首页 > 其它

面向对象与原型(三)

2016-01-13 16:49 405 查看
继承:

继承是面向对象中一个比较核心的概念。其他正统面向对象语言都会用两种方式实现继

承: 一个是接口实现, 一个是继承。 而ECMAScript只支持继承, 不支持接口实现,而实

现继承的方式依靠原型链完成。

function Box(){ //Box构造
this.name='Lee';
}
function Desk(){ //Desk构造
this.age=100;
}
Desk.prototype=new Box(); //Desc继承了Box, 通过原型, 形成链条
var desk=new Desk();
alert(desk.age);
alert(desk.name); //得到被继承的属性
function Table(){ //Table构造
this.level='AAAAA';
}
Table.prototype=new Desk(); //继续原型链继承
var table=new Table();
alert(table.name); //继承了Box和Desk

原型链继承图





在JavaScript里,被继承的函数称为超类型(父类,基类也行,其他语言叫法),继承的函数称为

子类型(子类,派生类)。继承也有之前问题,比如字面量重写原型会中断关系, 使用引用类型的原型

,并且子类型还无法给超类型传递参数。为了解决引用共享和超类型无法传参的问题,我们采用一种

叫借用构造函数的技术,或者成为对象冒充(伪造对象、经典继承)的技术来解决这两种问题。

function Box(age){

this.name=['Lee','Jack','Hello']

this.age=age;

}

function Desk(age){

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

}

var desk = new Desk(200);

alert(desk.age);

alert(desk.name);

desk.name.push('AAA'); //添加的新数据,只给 desk

alert(desk.name);

借用构造函数虽然解决了刚才两种问题, 但没有原型, 复用则无从谈起。 所以, 我们需要

原型链+借用构造函数的模式,这种模式成为组合继承。

function Box(age) {

this.name = ['Lee', 'Jack', 'Hello']

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

还有一种继承模式叫做:原型式继承;这种继承借助原型并基于已有的对象创建新对象,

同时还不必因此创建自定义类型。

function obj(o) { //传递一个字面量函数

function F() {} //创建一个构造函数

F.prototype = o; //把字面量函数赋值给构造函数的原型

return new F(); //最终返回出实例化的构造函数

}

var box = { //字面量对象

name : 'Lee',

arr : ['哥哥','妹妹','姐姐']

};

var box1 = obj(box); //传递

alert(box1.name);

box1.name = 'Jack';

alert(box1.name);

alert(box1.arr);

box1.arr.push('父母');

alert(box1.arr);

var box2 = obj(box); //传递

alert(box2.name);

alert(box2.arr); //引用类型共享了

寄生式继承把原型式+工厂模式结合而来,目的是为了封装创建对象的过程。

function create(o) { //封装创建过程

var f= obj(o);

f.run= function () {

return this.arr; //同样,会共享引用

};

return f;

}

组合式继承是 JavaScript最常用的继承模式; 但, 组合式继承也有一点小问题, 就是超

型在使用过程中会被调用两次: 一次是创建子类型的时候, 另一次是在子类型构造函数的部。

function Box(name) {

this.name = name;

this.arr = ['哥哥','妹妹','父母'];

}

Box.prototype.run= function() {

returnthis.name;

};

function Desk(name, age) {

Box.call(this, name); //第二次调用 Box

this.age = age;

}

Desk.prototype = newBox(); //第一次调用 Box

以上代码是之前的组合继承,那么寄生组合继承,解决了两次调用的问题。

function obj(o) {

functionF() {}

F.prototype= o;

return new F();

}

function create(box,desk){

var f=obj(box.prototype);

f.constructor=desk;

desk.prototype=f;

}

function Box(name){

this.name=name;

this.arr=['哥哥','妹妹','父母'];

}

Box.prototype.run=function(){

return this.name;

};

function Desk(name,age){

Box.call(this,name);

this.age=age;

}

create(Box,Desk); //通过这里实现继承

var desk=new Desk('Lee',100);

desk.arr.push('姐姐');

alert(desk.arr);

alert(desk.run()); //只共享了方法

var desk2=new Desk('Jack',200);

alert(desk2.arr); //引用问题解决
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: