(4)JavaScript继承模式二
2019-04-22 本文已影响0人
jaimor
上一篇文章说了继承模式,其实上一章节的继承模式是有一点瑕疵的,这个瑕疵并不是由模式引起的,而是由JavaScript自身原型链引起的。比如我们来改一改上一章节(请先看上一篇文章,这里不做阐述)中的代码:
//父类
function Supper(msg) {
this.msg = msg;
this.supperVal = ["supper", "val"]; //只将此处修改为引用类型,其他不做修改
}
Supper.prototype.say = function () {
console.log(this.msg);
}
Supper.prototype.getSupperVal = function () {
return this.supperVal;
}
new Supper("i am supper").say(); // i am supper
//子类
function Sub(msg) {
this.name = "sub"; //对父类的拓展,父类没有,而子类有的属性
this.msg = msg; //覆盖、修改父类的属性
}
Sub.prototype = new Supper("supper class"); //这里只是修改了父类的msg
//拓展了一个新的方法、功能
Sub.prototype.who = function () {
console.log(this.name);
}
var sub = new Sub("i am sub"); //子类msg为 i am sub
sub.who(); // sub,这里是对父类的属性、方法进行的拓展
sub.say(); // i am sub,这里是对父类的属性进行覆盖
sub.getSupperVal(); //supperVal,这里是对父类的属性进行继承
sub实例对象
然后我们来创建一个sub2实例。
var sub2 = new Sub("i am sub2");
sub2实例对象
这样也没有问题。拥有了自己的属性name,也覆盖了父类属性msg,也继承了父类属性supperVal和方法。看似都很完美,接下来注意了。我们要来修改下sub2中冲父类继承过来的属性supperVal。
sub2.supperVal.push("sub2 modify"); //愿意只是向修改sub2中的supperVal的值,但结果却不是这样!!!
修改后的结果
可以看到的是,我仅仅只是使用sub2修改自己的supperVal的值,但是影响到了其他实例的属性,这在开发中可要造成严重的BUG,值得注意!!!当然,如果supperVal是非引用类型,是不会有这样的问题的,而为什么使用引用类型的时候,会出现这样的问题,这就是JavaScript自身原型链里的知识了,这里不做阐述。我们这里主要是要完善这种继承模式中可能会出现类似的问题。
出现这种问题的原因就是,子类继承的过来的属性在原型链上。所以如果我们将父类继承过来的属性嵌入到子类中,而不是原型链中,岂不是就可以了。
// 子类做一点小修改,规避这样的问题
//子类
function Sub(msg) {
Supper.call(this, msg); //这里就将父类中的属性全部在子类中执行一边(相当于拷贝了一份在子类中)
this.name = "sub"; //对父类的拓展,父类没有,而子类有的属性
//this.msg = msg; //此处就不需要了
}
Sub.prototype = new Supper("supper class"); //这里的目的就只是拷贝父类原型链中的方法(因为属性已经通过Supper.call(this, msg)拷贝了)
完整代码如下:
//父类
function Supper(msg) {
this.msg = msg;
this.supperVal = ["supper", "val"]; //只将此处修改为引用类型,其他不做修改
}
Supper.prototype.say = function () {
console.log(this.msg);
}
Supper.prototype.getSupperVal = function () {
return this.supperVal;
}
new Supper("i am supper").say(); // i am supper
//子类
function Sub(msg) {
Supper.call(this, msg); //这里就将父类中的属性全部在子类中执行一边(相当于拷贝了一份在子类中)
this.name = "sub"; //对父类的拓展,父类没有,而子类有的属性
//this.msg = msg; //此处就不需要了
}
Sub.prototype = new Supper("supper class"); //这里只是修改了父类的msg
//拓展了一个新的方法、功能
Sub.prototype.who = function () {
console.log(this.name);
}
var sub = new Sub("i am sub"); //子类msg为 i am sub
var sub2 = new Sub("i am sub2");
sub2.supperVal.push("sub2 modify");
结果