在js中,call,apply和prototype都可以实现对象的继承,下面我们看一个例子:
function FatherObj1() {
this.sayhello = "I am join";
this.show = function () {
alert("I am FatherObj1");
};
this.getall = function () { if (arguments)
alert("GetAll:" + arguments[0]);
} }
function FatherObj2() {
this.sayhi = "I am Tom";
this.show = function () {
alert("I am FatherObj2");
}; }
function SonObj() {
this.sayby = "ByeBye";
this.show = function () {
alert("I am SonObj");
}; }
1.call&apply继承
我们先说一下 call和apply 的继承方式,
对于call和apply 在实现继承方面只是传参方式有区别,其他基本相同。
SonObj来继承FatherObj1:
function SonObj() {
this.sayby = "ByeBye";
this.show = function () {
alert("I am SonObj");
};
FatherObj1.call(this); //继承方式1
// FatherObj1.apply(this);//继承方式2 }
这里的 FatherObj1.call(this); 可以理解为把FatherObj1这个对象里的属性和方法委托给this也就是Sonobj,或者遗传给Sonobj,这种方式与C#,Java的继承不同的是:js可以继承多个父类,而C#,java只能继承一个,
那么问题来了,js继承多个父类,而多个父类如果有同名方法或者同名属性,会发生什么事情?
function SonObj() {
this.sayby = "ByeBye";
this.show = function () {
alert("I am SonObj");
};
FatherObj1.call(this); //继承方式1
FatherObj2.call(this); }
上面代码我让SonObj同时继承FatherObj1和FatherObj2,大家可以看到,在子类和父类对象里都存在同名方法show,
var son = new SonObj();
son.show();
运行之后的结果是:I am FatherObj2,这个结果说明 FatherObj2的show方法把SonObj的同名方法给重写了,下面我调整一下SonObj里面的方法顺序,
function SonObj() {
this.sayby = "ByeBye"; FatherObj1.call(this); //继承方式1
FatherObj2.call(this);
this.show = function () {
alert("I am SonObj");
}; }
输出结果:I am SonObj,可见js对同名方法的处理是,执行过程中,后者替代前者,不受子父类的约束,
如果我只想继承FatherObj1的getall方法,不想继承整个类怎么做呢?我们可以这样:
function SonObj() {
this.sayby = "ByeBye"; this.show = function () {
alert("I am SonObj");
};
}
var son = new SonObj();
var fa = new FatherObj1();
fa.getall.call(son, 1, 2);
fa.getall.apply(son, [1, 2]);
从call和apply 的调用上看,细心的同学应该发现了其中的不同,call的参数是 call(obj,arg1,arg2),而apply的参数是一个对象加一个数组,apply(obj,[arg1,arg2])
我现在给FatherObj2加一个原型方法:
FatherObj2.prototype.StaticForYou = function () {
alert("FatherObj2_StaticForYou"); };
现在我用SonObj去继承这个方法的话,可以这样写:
FatherObj2.prototype.StaticForYou.call(SonObj.prototype);
或者:
FatherObj2.prototype.StaticForYou.call(SonObj);
同样,用apply也可以实现,只是很相同,就不写了。
2 Prototype的继承:
SonObj.prototype = new FatherObj1();
var son = new SonObj();
这样,son就有了fatherobj1的所有方法,
同样,我们用son来调用show方法
son.show();
输出结果是:I am SonObj,而不是父类的方法返回结果,是的,prototype的继承其实就是复制父类的方法和属性,如果自己有同名方法或属性,就不去复制,而保留本身的属性或方法。
那如果我想要调用父类的同名方法怎么做呢?可以把上面代码改成
var father = new FatherObj1();
father.show.call(son);
这样相当于又回到了call和apply的继承问题。
现在我们想,既然用call和apply 可以继承多个父类,那我们同理用prototype来试试:
SonObj.prototype = new FatherObj1();
SonObj.prototype = new FatherObj2();
这样sonobj会不会继承这两个父类的属性和方法呢?
结果我们发现,已经调用不到FatherObj1的方法了,只能调用到FatherObj2的方法和属性。下面的父类把上面的父类替换掉了。
SonObj.prototype.StaticForYou = function () {
alert("Static_Come");
}
son.StaticForYou();
输出结果:Static_Come,如果想输出父类的原型方法呢?推一下就出来啦
FatherObj2.prototype.StaticForYou.call(SonObj);