JavaScript中继承的多种方式和优缺点
1. 原型链继承
优点:
- 无
缺点:
- 创建子类实例时,不能向父类的构造函数中传递参数
- 父类中所有引用类型的属性会被所有子类实例共享,也就说一个子类实例修改了父类中的某个引用类型的属性时,其他子类实例也会受到影响
function Parent() {
this.name = "parent";
this.hobby = ["sing", "rap"];
}
function Child() {
this.type = "child";
}
Child.prototype = new Parent();
let child1 = new Child();
let child2 = new Child();
child1.hobby.push("basketball");
console.log(child1.hobby); // [ 'sing', 'rap', 'basketball' ]
console.log(child2.hobby); // [ 'sing', 'rap', 'basketball' ]
2. 借用构造函数继承(经典继承)
优点:
- 在子类构造函数中可以向父类的构造函数中传递参数
- 避免了父类中的引用类型属性在子类中共享的问题
缺点:
- 父类原型对象上的方法子类继承不到
function Parent(age) {
this.name = "parent";
this.age = age;
this.hobby = ["sing", "rap"];
}
Parent.prototype.sayHi = function() {
console.log("Hi");
};
function Child(age) {
Parent.call(this, age);
this.type = "child";
}
let child1 = new Child(15);
let child2 = new Child(15);
child1.hobby.push("basketball");
console.log(child1.name); // parent
console.log(child1.age); // 15
console.log(child1.type); // child
console.log(child1.hobby); // [ 'sing', 'rap', 'basketball' ]
console.log(child2.hobby); // [ 'sing', 'rap' ]
child1.sayHi(); // 报错,child1.sayHi is not a function
3. 组合继承
优点:
- 在子类构造函数中可以向父类的构造函数中传递参数
- 避免了父类中的引用类型属性在子类中共享的问题
- 父类原型对象上的方法子类也可以继承到
缺点:
- 父类构造函数被调用了两次
function Parent(age) {
this.name = "parent";
this.age = age;
this.hobby = ["sing", "rap"];
}
Parent.prototype.sayHi = function() {
console.log("Hi");
};
function Child(age) {
Parent.call(this, age); // 第二次调用Parent
this.type = "child";
}
Child.prototype = new Parent(); // 第一次调用Parent
Child.prototype.constructor = Child;
let child1 = new Child(15);
let child2 = new Child(15);
child1.hobby.push("basketball");
console.log(child1.name); // parent
console.log(child1.age); // 15
console.log(child1.type); // child
console.log(child1.hobby); // [ 'sing', 'rap', 'basketball' ]
console.log(child2.hobby); // [ 'sing', 'rap' ]
child1.sayHi(); // Hi
4. 组合式继承优化1
优点:
- 在子类构造函数中可以向父类的构造函数中传递参数
- 避免了父类中的引用类型属性在子类中共享的问题
- 父类原型对象上的方法子类也可以继承到
- 父类构造函数也只调用了一次
缺点:
- 向子类原型上增加属性或方法时会影响到父类原型
function Parent(age) {
this.name = "parent";
this.age = age;
this.hobby = ["sing", "rap"];
}
Parent.prototype.sayHi = function() {
console.log("Hi");
};
function Child(age) {
Parent.call(this, age);
this.type = "child";
}
Child.prototype = Parent.prototype;
Child.prototype.constructor = Child;
// 向子类原型上增加testProp属性,同时会被添加到父类原型上
Child.prototype.testProp = 1
console.log(Parent.prototype); // 1
let child1 = new Child(15);
let child2 = new Child(15);
child1.hobby.push("basketball");
console.log(child1.name); // parent
console.log(child1.age); // 15
console.log(child1.type); // child
console.log(child1.hobby); // [ 'sing', 'rap', 'basketball' ]
console.log(child2.hobby); // [ 'sing', 'rap' ]
child1.sayHi(); // Hi
5. 组合式继承优化2
优点:
- 实现继承最有效的方式!
缺点:
- 无
function Parent(age) {
this.name = "parent";
this.age = age;
this.hobby = ["sing", "rap"];
}
Parent.prototype.sayHi = function() {
console.log("Hi");
};
function Child(age) {
Parent.call(this, age);
this.type = "child";
}
Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child;
let child1 = new Child(15);
let child2 = new Child(15);
child1.hobby.push("basketball");
console.log(child1.name); // parent
console.log(child1.age); // 15
console.log(child1.type); // child
console.log(child1.hobby); // [ 'sing', 'rap', 'basketball' ]
console.log(child2.hobby); // [ 'sing', 'rap' ]
child1.sayHi(); // Hi
(完)
免责声明
- 本博客所有文章仅用于学习、研究和交流目的,欢迎非商业性质转载。
- 博主在此发文(包括但不限于汉字、拼音、拉丁字母)均为随意敲击键盘所出,用于检验本人电脑键盘录入、屏幕显示的机械、光电性能,并不代表本人局部或全部同意、支持或者反对观点。如需要详查请直接与键盘生产厂商法人代表联系。挖井挑水无水表,不会网购无快递。
- 博主的文章没有高度、深度和广度,只是凑字数。由于博主的水平不高(其实是个菜B),不足和错误之处在所难免,希望大家能够批评指出。
- 博主是利用读书、参考、引用、抄袭、复制和粘贴等多种方式打造成自己的文章,请原谅博主成为一个无耻的文档搬运工!
posted on 2020-04-03 19:00 难凉热血,码梦为生! 阅读(430) 评论(3) 编辑 收藏 举报