javaScript基础:继承

一、简介

继承是面向对象中一个比较核心的概念。

其他正统面向对象语言都会用两种方式实现继承:一个是接口实现,一个是继承。

ECMAScript只支持继承,不支持接口实现。

二、实现继承-原型链

1、代码

//定义一个父类
function Father (money){
 this.money = money;
}

//定义一个子类
function Son (age){
 this.age = age;
}


/*说明:
new Father ();新创建一个Father类型的实例对象,这个实例对象包含了Father类的原型对象信息和构造函数信息。
将新创建的这个心对象赋值给Son类型的原型对象,相当于所有的Son类型的实例在创建时都包含了Father类型的原型对象信息、构造函数信息、还有自身的构造函数信息。
以上通过设置原型对象属性的方法完成了继承关系,这种方式叫做原型链。
 */
Son.prototype = new Father(1000);//此行代码就完成了子类继承父类</span>

var son = new Son(18);//创建一个子类实例对象
alert(son.money);//1000 子类实例对象具有money属性。
2、从属关系

//从属关系:所有的对象都从属于Object类型
//子类从属与父类
var father = new Father();
var son = new Son();
alert(father instanceof Object);//true
alert(son instanceof Object);//true
alert(son instanceof Father);//true
alert(father instanceof Son);//false

3、就近原则

当一个类型中的父类有属性A,而子类的构造函数中也有属性A时,应当取父类的A属性还是子类的属性A;

每个对象都有一个构造函数和原型对象,当构造函数和原型对象里具有一个同名的属性时,系统会先在构造函数里查找,有的话直接返回,没有的话再去原型对象里寻找。这就是所谓的就近原则,也更好的实现了共享与自身的灵活性。换句话说就是自己有的东西就不去原型那里取,自己没有就去找原型要,原型也没有就彻底没有了。

子类继承父类,继承的父类的构造函数和原型对象。将父类的构造函数和原型对象作为子类的原型对象,所以当子类的构造函数里有属性A就直接返回,没有的话就去自己的原型对象取,也就是父类里取。所以继承关系也符合就近原则。

//定义一个父类
function Father (){
 this.money = 1000;
}

//定义一个子类
function Son (){
 this.money = 2000;
 this.age = 18;
}
Son.prototype = new Father();
var son = new Son();
alert(son.money);//2000 自己有就不会取父类里的money
4、存在问题

通过原型链实现继承存在问题:

第一个:子类的prototype是父类的一个实例对象,存储的信息是固定的。不能从子类进行传参。

第二个:字面量重写原型会中断关系。Son.prototype = new Object();重写后断开继承关系 

三、实现继承-对象冒充

1.代码

//定义一个父类
function Father (money){
 this.money = money;
}

//定义一个子类
function Son (money,age){
 // 个人觉得:
 // 此处是当普通函数使用的。
 // 使用对象冒充之后Son的实例对象可以调用Father这个方法
 // 调用Father方法之后实例对象就增加了money属性。也就相当于从父类继承来了money属性,并且参数是子类传的。
 Father.call(this,money);
 this.age = age;
}

var son = new Son(1000,18);
alert(son.money);//1000
alert(son.age);//18
2.存在问题

借用对象冒充虽然解决了刚才两种问题,但没有原型,复用则无从谈起。所以,我们需要 原型链+对象冒充 的模式,这种模式成为组合继承。 

四、原型链+对象冒充

//定义一个父类
function Father (money){
 this.money = money;
}
Father.prototype.run = function (){
 return '这是父类方法....';
};

//定义一个子类
function Son (money,age){
 Father.call(this,money);
 this.age = age;
}

Son.prototype = new Father();//个人觉得应该加上:Son.prototype.constructor = Son;这行代码
//个人觉得:对象冒充使子类有了一个money属性,而原型链也使子类有了一个money属性,只不过这个money属性是存在原型对象里,会就近原则被隐藏掉。
var son = new Son(1000,18);
alert(son.money);//1000
alert(son.age);//18
alert(son.run());//这是父类方法...

五、组合模式

//临时中转函数
function obj(o) {				
	function F() {}				
	F.prototype = o;			
	return new F();			
}


//完成继承关系。要想在子类的原型对象里增加新的属性可以在这个方法内完成。个人觉得:也可以在中转函数中完成
function create(Father, Son) {
	var f = obj(Father.prototype);
	f.constructor = Son;				//调整原型对象的构造指针
	son.prototype = f;
}
//定义父类型
function Father(name, age) {
	this.name = name;
	this.age = age;
}

Father.prototype.run = function () {
return this.name + this.age + '运行中...'
}
function Son(name, age) {
    Father.call(this, name, age); //
}
//创建对象
create(Father, Son); //创建继承关系的函数
var son = new Son('Lee', 100);
alert(son.run());
alert(son.constructor);


 








  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值