前言
这次想讲一些对象继承的方式,主要有原型链继承,经典组合继承,寄生组合继承。
原型链继承
主要是通过原型链实现继承,此方法有很多弊端,不推荐。
function Person() {
this.name = "aaa"
this.friends = [1,2]
}
Person.prototype.eating = function() { console.log(this.name + " eating~")}
function Student() {
this.sno = 111
}
Student.prototype = new Person() // 改变子类的原型
Student.prototype.studying = function() { console.log(this.name + " studying~")}
const stu = new Student()
# 弊端
1. 打印对象时,继承的属性是看不到的
console.log(stu); // Person { sno: 111 }
console.log(stu.name); // aaa
2. 无法传递参数
3. 属性被多个对象共享时,如果属性是一个引用类型,引用类型会共享
const stu = new Student()
const stu2 = new Student()
console.log(stu.friends); // [ 1, 2 ]
stu2.friends[0] = 5
console.log(stu.friends); // [ 5, 2 ]
经典组合继承
function Person(name, age, friends) {
this.name = name
this.age = age
this.friends = friends
}
function Student(name, age, friends, sno) {
Person.call(this, name, age, friends)
this.sno = 111
}
var p = new Person()
Student.prototype = p
var stu = new Student("why", 18, ["kobe"], 111)
# 弊端
1. Person函数至少被调用了两次
2. 所有的子类对象会拥有两份父类的属性,一份在子类实例上,一份在子类的原型对象中
寄生组合继承
推荐使用的继承方法。
function inheritPrototype(SubType, SuperType) {
SubType.prototype = Object.create(SuperType.prototype)
// 这一步一定要操作,constructor属性重新指回自己
Object.defineProperty(SubType.prototype, "constructor", {
enumerable: false,
configurable: true,
writable: true,
value: SubType
})
}
function Person(name, age, friends) {
this.name = name
this.age = age
this.friends = friends
}
Person.prototype.eating = function() { console.log("eating~")}
function Student(name, age, friends, sno, score) {
Person.call(this, name, age, friends)
this.sno = sno
this.score = score
}
inheritPrototype(Student, Person)
Student.prototype.studying = function() { console.log("studying~")}
var stu = new Student("why", 18, ["kobe"], 111, 100)
stu.eating() // eating~
console.log(Student.prototype); // Person { studying: [Function (anonymous)] }
console.log(Student.prototype.constructor); // [Function: Student]
总结
这几种方法都可以实现对象的继承,推荐使用最后一种寄生组合继承,这是我跟一位大佬(coderwhy王元红老师)学的。