继承的3种优缺点
new执行过程
const person = new Person(args);
//相当于
const person = Person.new(args);
Function.prototype.new = function(){
let obj = new Object();
obj.__proto__ = this.prototype;
const ret = this.apply(obj, arguments);
return (typeof ret == 'object' && ret) || obj;
}
复制代码
- 原型链继承
// (1) 父类
function Persion(name,age){
this.name = name;
this.age = age;
}
// 父类的原型对象属性
Persion.prototype.id = 10;
// 子类
function Boy(sex){
this.sex = sex;
}
// 继承实现
Boy.prototype = new Persion('c5',27);
var b = new Boy();
alert(b.name)// c5
alert(b.id)//10
// (2) 父类
function Parent(age) {
this.name = ['2','4'];
this.age = age;
}
// 父类的原型对象属性
Parent.prototype.getName = function(){
return this.name
};
// 子类
function Child(sex) {
}
Child.prototype = new Parent(23)
var child = new Child();
child.name.push('6');
console.log(child.name);//["2", "4", "6"]
console.log(child.getName());//["2", "4", "6"]
var child2 = new Child();
console.log(child2.name);//["2", "4", "6"]
复制代码
优点:既继承了父类的模板,又继承了父类的原型对象。优点是继承了父类的模板,又继承了父类的原型对象,缺点就是父类实例传参,不是子类实例化传参,不符合常规语言的写法,而且引用类型的属性被所有实例共享(2)。
- 类继承(继承父类构造函数,但不继承父类的原型)避免了引用类型[m]的属性被所有属性共享;可以在Child向Parent传参。[经典继承] 缺点:方法只能在构造函数中定义,每次创建实例都会开辟空间给方法。
function Parent(name, age) {
this.name = name;
this.age = age;
this.m=["ghg",'ghjg','fghf']
}
// 父类的原型对象属性
Parent.prototype.getName = function () {
return this.name
};
// 子类
function Child(sex,name,age) {
Parent.call(this, name, age)
this.sex = sex;
}
var child = new Child('女','石婷',22);
child.m.push('bhjb')
// console.log(child.getName());// Uncaught TypeError: child.getName is not a function
console.log(`性别:${child.sex} 姓名:${child.name} 年龄:${child.age}`);
console.log(child.m);// ["ghg", "ghjg", "fghf", "bhjb"]
// 性别:女 姓名:石婷 年龄:22
var child2 = new Child('女', '敖子琼', 22);
// console.log(child.getName());// Uncaught TypeError: child.getName is not a function
console.log(`性别:${child2.sex} 姓名:${child2.name} 年龄:${child2.age}`);
// 性别:女 姓名:敖子琼 年龄:22
console.log(child2.m);// ["ghg", "ghjg", "fghf"]
复制代码
- 组合继承(原型链和经典) 解决引用属性实例共享和不能继承父类原型链上的属性;缺点:两次调用Parent构造函数
function Parent(name) {
this.name = name;
this.m=["ghg",'ghjg','fghf']
}
// 父类的原型对象属性
Parent.prototype.getName = function () {
return this.name
};
// 子类
function Child(sex,name) {
Parent.call(this, name)
this.sex = sex;
}
Child.prototype=new Parent()
var child = new Child('女','石婷');
child.m.push('bhjb')
console.log(child.getName());// 石婷
console.log(`性别:${child.sex} 姓名:${child.name} `);
console.log(child.m);// ["ghg", "ghjg", "fghf", "bhjb"]
// 性别:女 姓名:石婷 年龄:22
var child2 = new Child('女', '敖子琼');
console.log(`性别:${child2.sex} 姓名:${child2.name} `);
// 性别:undefined 姓名:石婷 年龄:22
console.log(child2.m);// ["ghg", "ghjg", "fghf"]
复制代码
- 后面再补组合继承
- ES6 class
// class 实现类的继承
class Parent{
// 相当于构造函数
constructor(name){
this.name=name;
}
// 相当于原型
sayName(){
console.log(this.name);
}
}
class Child extends Parent{
// 相当于构造函数
constructor(childName,age) {
// super相当于 把类的原型拿过来
// 以及Parent.call(this, childName)
super(childName);
this.age = age;
}
// 相当于原型
getAge() {
console.log(this.age);
}
}
let a = new Child('daisy',24)
a.sayName(); //汪某
a.getAge(); // 24
复制代码