js继承的几种方式
1、原型链继承
优点:父类放方法可以复用
缺点:父类所有的应用数据类型(对象,数组)会被子类共享更改一个类的数据,其他数据会受到影响,一直变化。
function Person() {
this.name = "小明"
this.eats = ['苹果']
this.getName = function () {
console.log(this.name);
}
}
//person原型的方法
Person.prototype.get = () => {
console.log('Person.prototype上的方法');
}
function Student() { }
Student.prototype = new Person()
const stu1 = new Student()
stu1.name = '小花'
stu1.eats.push('香蕉')
console.log(stu1.name);
console.log(stu1.eats);
stu1.getName()
stu1.get()
console.log('-----------------------------');
const stu2 = new Student()
console.log(stu2.name);
console.log(stu2.eats);
stu2.getName()
stu2.get()
2、构造函数的继承
优点:父类的引用数据类型的数据不会被子类共享 不会相互影响。
缺点:子类不能访问父类数据的方法和参数
function Person() {
this.name = "小明"
this.eats = ['苹果']
this.getName = function () {
console.log(this.name);
}
}
//person原型的方法
Person.prototype.get = () => {
console.log('Person.prototype上的方法');
}
function Student(){
Person.call(this)
}
const stu1 = new Student()
stu1.name = '小花'
stu1.eats.push('香蕉')
console.log(stu1.name);
console.log(stu1.eats);
stu1.getName()
//stu1.get() 报错
console.log('-----------------------------');
const stu2 = new Student()
console.log(stu2.name);
console.log(stu2.eats);
stu2.getName()
//stu2.get() 报错
3、组合式继承
优点:
1、父类可以复用
2、父类构造函数中的引用属性数据不会被子类共享 不会相互影响
缺点:会调用两次父类构造函数,会有两份一样的属性和方法 影响性能
function Person() {
this.name = "小明"
this.eats = ['苹果']
this.getName = function () {
console.log(this.name);
}
}
//person原型的方法
Person.prototype.get = () => {
console.log('Person.prototype上的方法');
}
function Student() {
Person.call(this)
}
Student.prototype = new Person()
const stu1 = new Student()
stu1.name = '小花'
stu1.eats.push('香蕉')
console.log(stu1.name);
console.log(stu1.eats);
stu1.getName()
stu1.get()
console.log('-----------------------------');
const stu2 = new Student()
console.log(stu2.name);
console.log(stu2.eats);
stu2.getName()
stu2.get()
console.log(stu2); //会输出两份 影响性能
4、寄生组合继承(推荐)
目前最优方案
function Person() {
this.name = "小明"
this.eats = ['苹果']
this.getName = function () {
console.log(this.name);
}
}
//person原型的方法
Person.prototype.get = () => {
console.log('Person.prototype上的方法');
}
function Student() {
Person.call(this)
}
const Fn = function () { }
Fn.prototype = Person.prototype
Student.prototype = new Fn()
const stu1 = new Student()
stu1.name = '小花'
stu1.eats.push('香蕉')
console.log(stu1.name);
console.log(stu1.eats);
stu1.getName()
stu1.get()
console.log('-----------------------------');
const stu2 = new Student()
console.log(stu2.name);
console.log(stu2.eats);
stu2.getName()
stu2.get()
console.log(stu2);
5、ES6 class继承 推荐
目前最优方案
class Person {
constructor() {
this.name = '小明'
this.eats = ['苹果']
this.getName = function () {
console.log(this.name);
}
}
get = () => {
console.log('Person.prototype上的方法');
}
}
class Student extends Person { }
const stu1 = new Student()
stu1.name = '小花'
stu1.eats.push('香蕉')
console.log(stu1.name);
console.log(stu1.eats);
stu1.getName()
stu1.get()
console.log('-----------------------------');
const stu2 = new Student()
console.log(stu2.name);
console.log(stu2.eats);
stu2.getName()
stu2.get()
总结:
js的继承有5种方式:
原型链继承
构造函数继承
组合继承
以上三种相对都会有一定的确缺陷
更推荐以下两种
class继承
寄生组合继承