原型继承
function Person() {
this.name = '小明'
this.fruits = ['苹果']
this.getName = function () {
console.log(this.name)
}
}
Person.prototype.get = function () {
console.log('Person.prototype上的方法')
}
function Student() {}
Student.prototype = new Person()
优点:
-
方法复用
-
由于方法定义在父类的原型上,复用了父类构造函数原型上的方法。
const stu1 = new Student()
console.log(stu1.name); //小明
console.log(stu1.fruits); //['苹果]
stu1.getName() //小明
stu1.get() //Person.prototype上的方法
缺点:
-
创建的子类实例不能传参。
-
父类所有的引用类型数据 (对象,数组) 会被子类共享更改一个子类的数据,其他数据会受到影响,一起变化
const stu1 = new Student()
const stu2 = new Student()
stu1.name = '小花'
stu1.fruits.push("香蕉")
console.log(stu1.name); //小花
console.log(stu1.fruits); //['苹果','香蕉']
stu1.getName() //小花
stu1.get() //Person.prototype上的方法
console.log(stu2.name) //小明
console.log(stu2.fruits) //['苹果','香蕉']
stu2.getName() //小明
stu2.get() //Person.prototype上的方法
构造函数继承
function Person() {
this.name = '小明'
this.fruits = ['苹果']
this.getName = function () {
console.log(this.name)
}
}
Person.prototype.get = function () {
console.log('Person.prototype上的方法')
}
function Student() {
Per.call(this)
}
优点
-
父类的引用类型的数据 (对象,数组) 不会被子类共享,不会相互影响
const stu1 = new Student()
const stu2 = new Student()
stu1.name = '小花'
stu1.fruits.push("香蕉")
console.log(stu1.name); //小花
console.log(stu1.fruits); //['苹果','香蕉']
stu1.getName() //小花
console.log(stu2.name) //小明
console.log(stu2.fruits) //['苹果']
stu2.getName() //小明
缺点
-
子类不能访问父类原型属性(Person.prototype)上的方法和参数
stu1.get() //Error
stu2.get() //Error
组合继承
function Person(name) {
this.name = name
this.fruits = ['苹果']
this.getName = function () {
console.log(this.name)
}
}
Person.prototype.get = function () {
console.log('Person.prototype上的方法')
}
function Student(name,age) {
Person.call(this,name)
this.age = age
}
Student.prototype = new Person()
优点
-
子类实例创建可以传递参数。
-
父类可以复用
-
父类构造函数中引用类型的数据 (对象,数组) 不会被子类共享
const stu1 = new Student('李白',18)
const stu2 = new Student('杜甫',20)
stu1.name = '诗仙'
stu1.fruits.push("香蕉")
console.log(stu1.name,stu1.age); //诗仙 18
console.log(stu1.fruits); //['苹果','香蕉']
stu1.getName() //诗仙
stu1.get() //Person.prototype上的方法
console.log(stu2.name,stu2.age) //杜甫 20
console.log(stu2.fruits) //['苹果']
stu2.getName() //杜甫
stu2.get() //Person.prototype上的方法
缺点
-
会调用两次父类的构造函数,会有两份一样的属性和方法,影响性能,造成了不必要的消耗。
寄生组合继承(常用)
function Person(name) {
this.name = name
this.fruits = ['苹果']
this.getName = function () {
console.log(this.name)
}
}
Person.prototype.get = function () {
console.log('Person.prototype上的方法')
}
function Student(name,age) {
Person.call(this,name)
this.age = age
}
const Fn = function(){}
Fn.prototype = Person.prototype
Student.prototype = new Fn()
核心思想: 组合继承 + 原型继承结合两者的优点。 优点: 完美! 缺点:无!
const stu1 = new Student('李白',18)
const stu2 = new Student('杜甫',20)
stu1.name = '诗仙'
stu1.fruits.push("香蕉")
console.log(stu1.name,stu1.age); //诗仙 18
console.log(stu1.fruits); //['苹果','香蕉']
stu1.getName() //诗仙
stu1.get() //Person.prototype上的方法
console.log(stu2.name,stu2.age) //杜甫 20
console.log(stu2.fruits) //['苹果']
stu2.getName() //杜甫
stu2.get() //Person.prototype上的方法
class类继承extends(常用)
class Person {
constructor(name) {
this.name = name
this.fruits = ['苹果']
this.getName = function () {
console.log(this.name)
}
}
get = function () {
console.log('Person.prototype上的方法')
}
}
class Student extends Person {
constructor(name,age) {
super(name) // 调用父类的constructor方法
this.age = age
}
}
js自己原生的继承方法
const stu1 = new Student('李白',18)
const stu2 = new Student('杜甫',20)
stu1.name = '诗仙'
stu1.fruits.push("香蕉")
console.log(stu1.name,stu1.age); //诗仙 18
console.log(stu1.fruits); //['苹果','香蕉']
stu1.getName() //诗仙
stu1.get() //Person.prototype上的方法
console.log(stu2.name,stu2.age) //杜甫 20
console.log(stu2.fruits) //['苹果']
stu2.getName() //杜甫
stu2.get() //Person.prototype上的方法