实现继承的方式
方式一:通过原型链实现继承(不推荐单独使用)
function Parent(age) {
this.lastName = 'wang';
this.age = age;
this.hobby = ['a', 'b'];
this.sayHi = function () {
console.log(123);
}
}
//在父类型的原型对象上定义方法
Parent.prototype.asset = function () {
console.log('我有一毛钱的资产');
};
//定义子类构造函数
function Child() {
}
//借用原型对象继承父类型所有属性及方法
Child.prototype = new Parent();
// 调用父类构造函数
var p = new Parent(28);
// 重复调用子类构造函数
var child = new Child(18);
var child1 = new Child();
//结论一: 修改普通数据类型的属性不会影响其他的=============
child.lastName = 'geng';
console.log(child.lastName);// 'geng'
console.log(child1.lastName);// 'wang'
console.log(p.lastName);// 'wang'
//结论二:创建子类型的实例的时候,不能传递参数==================
console.log(p.age);// 28
console.log(child.age); // underfined
//结论三:继承父类的属性如果是引用类型,对其中一个子类的属性进行修改,其他子类的该属性都会受到影响,父类不受影响========================
//修改一个子类型实例的属性 其他子类的全部都会受到影响,父类不受影响
child.hobby.push('c');
console.log(child.hobby); //["a", "b", "c"]
console.log(child1.hobby); //["a", "b", "c"]
console.log(p.hobby);//["a", "b"]
//结论四:修改方法不会影响父类及其他子类实例的方法=======================
//对比方法 1 父类构造函数原型对象上的方法
child.asset = function () {
console.log('我有一台笔记本');
}
child.asset(); //我有一台笔记本
child1.asset();//我有一毛钱的资产
p.asset();//我有一毛钱的资产
//对比方法 2 父类构造函数自身的方法
child.sayHi = function () {
console.log(234);
}
child.sayHi(); //234
child1.sayHi();//123
p.sayHi();//123
优点:
1 可以访问父类的属性和方法,也可以访问原型上的属性和方法
2 修改方法不会影响父类及其他子类实例的方法
缺点:
1 继承父类的属性如果是引用类型,对其中一个子类的属性进行修改,其他子类的全部都会受到影响;
2 创建子类型的实例的时候,不能传递参数
方式二:通过构造函数实现(call或apply)继承 (不推荐单独使用)
//父构造函数
function Parent(age) {
this.lastName = 'wang';
this.age = age;
this.hobby = ['a', 'b'];
this.sayHi = function () {
console.log(123);
}
}
//在父类型的原型对象上定义方法
Parent.prototype.asset = function () {
console.log('我有一毛钱的资产');
};
//子类构造函数
function Child(age) {
//子构造函数使用call方法调用父级构造函数继承父类的属性
Parent.call(this, age)
}
// 调用父类构造函数
var p = new Parent(28);
// 重复调用子类构造函数
var child = new Child(18);
var child1 = new Child();
//结论一: 修改普通数据类型的属性不会影响其他的=============
child.lastName = 'geng';
console.log(child.lastName);// 'geng'
console.log(child1.lastName);// 'wang'
console.log(p.lastName);// 'wang'
//结论二:创建子类型的实例的时候,可以传递参数==================
console.log(p.age);// 28
console.log(child.age); // 18
//结论三:可以保证每个子类维护自己的属性===============
child.hobby.push('c');
console.log(child.hobby); //["a", "b", "c"]
console.log(child1.hobby); //["a", "b"]
console.log(p.hobby);//["a", "b"]
//结论四:无法访问原型链上的方法==================
// 父类构造函数原型对象上的方法
child.asset(); //报错 child.asset is not a function
child1.asset();//报错 child.asset is not a function
p.asset();//我有一毛钱的资产
//结论五:修改继承到父类构造函数自身的方法不会影响父类及其他子类实例的方法============
// 父类构造函数自身的方法
child.sayHi = function () {
console.log(234);
}
child.sayHi(); //234
child1.sayHi();//123
p.sayHi();//123
优点:可以保证每个子类维护自己的属性
缺点:无法访问原型链上的方法
方式三:组合继承 将两个结合(借用原型对象继承方法,借用构造函数继承属性) js中最常用的继承方式。
function Parent(age) {
this.lastName = 'wang';
this.age = age;
this.hobby = ['a', 'b'];
this.sayHi = function () {
console.log(123);
}
}
//在父类型的原型对象上定义方法
Parent.prototype.asset = function () {
console.log('我有一毛钱的资产');
};
function Child(age) {
//子构造函数使用call方法调用父级构造函数继承父类的属性
Parent.call(this, age)
}
//子类原型对象等于实例化父类继承方法
Child.prototype = new Parent()
// 调用父类构造函数
var p = new Parent(28);
// 重复调用子类构造函数
var child = new Child(18);
var child1 = new Child();
//结论一: 修改普通数据类型的属性不会影响其他的=============
child.lastName = 'geng';
console.log(child.lastName);// 'geng'
console.log(child1.lastName);// 'wang'
console.log(p.lastName);// 'wang'
//结论二:创建子类型的实例的时候,能传递参数==================
console.log(p.age);// 28
console.log(child.age); //18
//结论三:每个子类可以维护自己属性===================
child.hobby.push('c');
console.log(child.hobby); //["a", "b", "c"]
console.log(child1.hobby); //["a", "b"]
console.log(p.hobby);//["a", "b"]
//结论四:修改方法不会影响父类及其他子类实例的方法==============
//对比方法 1 父类构造函数原型对象上的方法
child.asset = function () {
console.log('我有一台笔记本');
}
child.asset(); //我有一台笔记本
child1.asset();//我有一毛钱的资产
p.asset();//我有一毛钱的资产
//对比方法 2 父类构造函数自身的方法
child.sayHi = function () {
console.log(234);
}
child.sayHi(); //234
child1.sayHi();//123
p.sayHi();//123
优点:既可以访问原型上的属性和方法,每个子类可以维护自己属性
缺点:每次创建一个子类实例,父类都会被执行一次
方式四:ES6 之后使用 extends 关键字实现继承
// 使用类的继承(eatends和super)继承父亲的属性及方法
class Dad {
constructor(name, age) {
this.uname = name;
this.age = age
}
sayHi(song) {
console.log('我会唱' + song);
}
}
class Baby extends Dad {
//如果子类中定义了构造函数 constructor,则在构造函数的第一行必须调用 super()
constructor(uname, age) {
super(uname, age);
// this.sex = '男';
}
}
var baby = new Baby('儿子', 8);
console.log(baby.uname);
console.log(baby.age);
console.log(baby.sex);
baby.sayHi('嘎嘎嘎')
总结
提示:这里对文章进行总结:
例如:以上就是今天要讲的内容,本文仅仅简单介绍了实现继承的方式的使用,方式三:组合继承 将两个结合(借用原型对象继承方法,借用构造函数继承属性) 是js中最常用的继承方式.也是实现继承的最优选择.