这篇文章将主要关注Js的继承问题,如果能与上一篇《谈谈Js对象的那些事儿》一起看,那是极好不过的了。
首先,我们得清楚Js是没有类似Java那种显式继承机制的,但我们可以通过其本身的语言特性(prototype、call、apply)来模拟实现一定程度的对象继承。
1.使用对象冒充实现继承
实现原理:让父类的构造函数成为子类的方法,然后调用该子类的方法,以实现对象的继承。
var People = function(name,age){ //父对象,People
this.name = name;
this.age = age;
}
People.prototype.showPInfo = function(){
alert('姓名:'+this.name+'\n年龄:'+this.age);
}
var Men = function(){ //子对象,Men
this.people = People; //将对象People作为子对象的一个属性
this.people('yq','24');
delete this.people; //我们可以删除this.people属性后,看Men是否还具有People中的属性
this.gender = 'men';
}
Men.prototype.showMInfo = function(){
alert('姓名:'+this.name+'\n年龄:'+this.age+'\n性别:'+this.gender);
}
var men = new Men('men');
//men.people('oxygen','24');
men.showInfo(); //==>姓名:yq
// 年龄:24
// 性别:men
值得强调的是:使用这种)方法不能继承父对象通过prototype添加的属性和方法。
2.使用apply、call函数来变换作用域,以实现继承
首先说明一下apply和call方法的本质都一样,都是用来改变上下文作用域的,只是调用的方式不同而已。call与apply的第一个参数都是需要调用的函数对象(提供作用域---实例),在函数体内这个参数就是this的值,剩余的参数是需要传递给函数的值,call与apply的不同就是call传的值可以是任意的,而apply传的剩余值必须为数组。
1)call()方法:
var Parent = function(name,age){
this.name = name;
this.age = age;
}
var Child = function(child){
this.child = child;
}
Child.prototype.showInfo = function(){
alert('姓名:'+this.name+'\n年龄:'+this.age+'\n小孩:'+this.child);
}
var child = new Child('son');
Parent.call(child,'parent','40');
child.showInfo();
2)apply()方法:
var Parent = function(name,age){
this.name = name;
this.age = age;
this.showInfo = function(){
alert('姓名:'+this.name+'\n年龄:'+this.age+'\n小孩:'+this.child);
}
}
var Child = function(child){
this.child = child;
}
var child = new Child('son');
Parent.apply(child,['parent','40']);
child.showInfo();
值得强调的是:同样地,使用apply()和call()方法不能继承父对象通过prototype添加的属性和方法。
var Parent = function(){
this.name = 'parent';
this.age = 40;
}
var Child = function(child){
Parent.call(this);
this.child = child;
this.showChildInfo = function(){
alert('c姓名:'+this.name+'\nc年龄:'+this.age+'\nc小孩:'+this.child);
}
}
for(var key in Parent.prototype){
Child.prototype[key] = Parent.prototype[key];//一定要值传递,不能引用传递,否则将污染Parent,即不能直接使用Child.prototype = Parent.prototype;
}
var child = new Child('son');
child.name = 'child';
child.age = '10';
child.showChildInfo()
3.使用混合模式(构造函数+prototype),以实现继承
var Parent = function(){
this.name = 'parent';
this.age = 40;
}
var Child = function(child){
Parent.call(this);
this.child = child;
this.showChildInfo = function(){
alert('c姓名:'+this.name+'\nc年龄:'+this.age+'\nc小孩:'+this.child);
}
}
for(var key in Parent.prototype){
Child.prototype[key] = Parent.prototype[key];//一定要值传递,不能引用传递,否则将污染Parent,即不能直接使用Child.prototype = Parent.prototype;
}
var child = new Child('son');
child.name = 'child';
child.age = '10';
child.showChildInfo();