js继承问题的实现。
1)call的用法和理解:
调用对象的一个方法,以另一个对象代替当前对象。
例子1:
obj1.method1.call(obj2,argument1,argument2);//call的作用就是把obj1的方法method1放到对象obj2的身上实现,后面作为参数传进去。
function add(a,b){
document.writeln(a+b);
}
function sub(a,b){
document.writeln(a-b);
}
add.call(sub,3,1);//输出4,用的是add方法,放在sub里实现。
例子2:
function class1(name){
this.name = name;
this.showName = function(){
document.writeln(this.name);
}
}
function class2(name){
this.name = name;
}
var c1 = new class1('c1');
var c2 = new class2('c2');
c1.showName.call(c2);//输出c2
解释:把c1的showName方法放到c2上来实现,c2本来是没有showName方法的,这样c2调用了showName方法输出c2。
例子3(用call来实现继承):
function class1(){
this.showTxt = function(txt){
document.writeln(txt);
}
}
function class2(){
class1.call(this);
}
var c2 = new class2();
c2.showTxt('c2');
解释:这样class2就继承class1了,class1.call(this)的意思是:把class1的方法在this对象里使用,这样class2就可以使用class1的所有方法了。
例子4(实现多重继承):
function class1(){
this.showAdd = function(a,b){
document.writeln(a+b);
}
}
function class2(){
this.showSub = function(a,b){
document.writeln(a-b);
}
}
function class3(){
class1.call(this);
class2.call(this);
}
var c3 = new class3();
c3.showAdd(10,9);
c3.showSub(10,9);
2)js常用的两种继承。
1>原型链继承(对象间的继承):
function Parent(){
this.name = 'mike';
}
function Child(){
this.age = 12;
}
Child.prototype = new Parent();//Child继承了Parent,通过原型,形成链条
var c1 = new Child();
document.writeln(c1.age);
document.writeln(c1.name);//c1继承了Parent的属性
function Brother(){
this.weight = 60;
}
Brother.prototype = new Child();//Brother继承了Child,通过原型,形成链条
var brother = new Brother();
document.writeln(brother.name);
document.writeln(brother.age);
解释: 以上原型链继承还缺少一环,那就是Object,所有的构造函数都继承Object。而继承Object是自动完成的,并不需要我们自己手动继承。
PS:(1)确定原型和实例的关系:
可以通过两种方式来确定原型和实例之间的关系。操作符instanceof和isPrototypeof方法:
document.writeln(brother instanceof Object);
document.writeln(c1 instanceof Brother); //false
document.writeln(brother instanceof Child);
document.writeln(brother instanceof Parent);
(2)使用原型继承有两个问题:<1> 重写原型会中断关系<2>子类型还无法给超类型传递参数
2>类式继承(借用构造函数):
function Parent(age){
this.name = ['mike','joe','smith'];
this.age = age;
}
function Child(age){
Parent.call(this,age);
}
var c1 = new Child(21);
document.writeln(c1.age);
document.writeln(c1.name);
c1.name.push('bill');
document.writeln(c1.name);
解释: 借用构造函数虽然解决了刚才两种问题,但没有原型,则复用无从谈起,所以我们需要原型链+借用构造函数的模式,这种模式称为组合继承。
3)组合继承(原型链+类式继承)
例子:
function Parent(age){
this.name = ['mike','jack','smith'];
this.age = age;
}
Parent.prototype.run = function(){
return this.name + 'are both' + this.age;
};
function Child(age){
Parent.call(this,age);//给超类型传参数,借用构造函数
}
Child.prototype = new Parent();//原型链继承
var c1 = new Child(21);//写成Parent(21)也可以
document.writeln(c1.run());
解释: 组合式继承是比较常用的一种继承方法,其背后的思路是 使用原型链实现对原型属性和方法的继承,而通过借用构造函数来实现对实例属性的继承。
4)原型式继承
解释: 这种继承借助原型并基于已有的对象创建新对象,同时还不用创建自定义类型的方式称为原型式继承
例子:
function obj(o){
function F(){}
F.prototype = o;
return new F();
}
var box = {
name:'tiger',
arr:['brother','sister','father']
};
var b1 = obj(box);
document.writeln(b1.name+"<br>");
b1.name = 'mike';
document.writeln(b1.name+"<br>");
document.writeln(b1.arr+"<br>");
b1.arr.push('parents');
document.writeln(box.arr+"<br>");//b1插入后,父类的属性同样改变
document.writeln(b1.arr+"<br>");
var b2 = obj(box);
document.writeln(b2.name+"<br>");
document.writeln(b2.arr);
解释: 原型式继承首先在obj函数内部创建一个临时性的构造函数 ,然后将传入的对象作为这个构造函数的原型,最后返回这个临时类型的一个新实例。
5)寄生式继承
解释: 这种继承方式是把原型式+工厂模式结合起来,目的是为了封装创建的过程。
function obj(o){
function F(){}
F.prototype = o;
return new F();
}
function create(o){
var f = obj(o);
f.run = function(){
return this.arr;
};
return f;
}
var box = {
name:'tiger',
arr:['brother','sister','father']
};
var f1 = create(box);
document.writeln(f1.name+'<br>');
document.writeln(f1.arr+'<br>');
document.writeln(f1.run());
6)寄生组合式继承
解释: 但组合继承的超类型在使用过程中会被调用两次;一次是创建子类型的时候,另一次是在子类型构造函数的内部 ,寄生组合继承,解决了两次调用的问题。
例子:
function obj(o){
function F(){}
F.prototype = o;
return new F();
}
function inheritPrototype(child,parent){
var prototype = obj(parent.prototype);//创建对象
prototype.constructor = child;//增强对象
child.prototype = prototype;//自定对象
}
function parent(name){
this.name = name;
this.color = ['red','yellow','green'];
}
parent.prototype.sayName = function(){
document.writeln(this.name);
}
function child(age){
parent.call(this,name);
this.age = age;
}
inheritPrototype(child,parent);
child.prototype.sayAge = function(){
document.writeln(this.age);
}
var p1 = new parent('p1');
var c1 = new child('12');
document.writeln(p1.name+'<br>');
document.writeln(p1.age+'<br>');
document.writeln(p1.color+'<br>');
document.writeln(c1.name+'<br>');
document.writeln(c1.age+'<br>');
document.writeln(c1.sayName()+'<br>');