js 继承(子类拥有父类的属性和方法)
constructor:
function Parent (name){
this.name = name
this.arr = [1]
}
let Child = new Parent(‘张三’)
Parent.constructor = Function //constructor指向构造函数
Child.constructor = Parent
Child.prototype.constructor = Child
结论:函数的constructor在原型属性prototype上,执向函数本身。instance of 判断变量的构造函数时通过原型链去查找。
原型链继承
function Child1 (like) {
this.like = like
}
Child1.prototype = new Parent('张三')
Child1.prototype.constructor = Child1
console.log(Child1)
console.log(Child1.name)
console.log(Child1.prototype.name)
console.log(Child1.prototype.arr)
let body = new Child1()
console.log(body.name, body.arr)
// 结论:将父类的属性和方法放到子类的原型属性prototype上
// 缺点:不能向父类传参,并且拥有了一些子类不需要的属性和方法
构造函数继承
/* function Parent (name) {
this.name = name
this.sex = '男'
this.say = function () {
console.log('hello')
}
}
Parent.prototype.arr = [1, 2]
function Child (name, like) {
this.like = like
this.age = 18
Parent.myCall(this, name)
}
let body1 = new Child('张三', '打篮球')
let body2 = new Child('李四', '游泳')
console.log(body1)
console.log(body2) */
// 结论:通过call方法特性执行一次父类构造函数并将参数传进去,然后改变this指向,使子类拥有父类的属性和方法
// 优点:可以传参
// 缺点:1,没有共享父类的方法,2,不能继承原型链的属性
组合继承
/* function Parent (name) {
this.name = name
this.sex = '男'
this.say = function () {
console.log('hello')
}
}
Parent.prototype.arr = [1, 2]
function Child (name, like) {
this.like = like
this.age = 18
Parent.myCall(this, name)
}
Child.prototype = new Parent()
Child.prototype.constructor = Child
let body1 = new Child('张三', '打篮球')
let body2 = new Child('李四', '游泳') */
//结论:原型链继承和构造函数继承的组合版
//缺点:执行了两次构造函数,会多缓存一个内存
寄生组合继承
/* function Parent (name) {
this.name = name
this.sex = '男'
this.say = function () {
console.log('hello')
}
}
Parent.prototype.arr = [1, 2]
function Child (name, like) {
this.like = like
this.age = 18
Parent.myCall(this, name)
}
Child.prototype = Object.create(Parent.prototype) //创建一个新对象,并且将传入的对象设为新对象的__proto__
Child.prototype.constructor = Child
let body1 = new Child('张三', '打篮球')
let body2 = new Child('李四', '游泳')
console.log(body1);
console.log(body2); */
//结论:继承的完美解决方案
Es6的继承
class Person {
constructor(name, age) { //new 改类的时候会执行constructor(构造器)
this.name = name
this.age = age
this.sex = '男'
return null
}
say () { // 这种直接定义在类上的方法是挂在该类的prototype上的
console.log(1)
}
static like = 'sport'
static sayHello () { // 直接通过该类.方法就可以获取
console.log('hello')
}
}
class Student extends Person {
constructor() {
// console.log(this);
// console.log(super);
super('zs')
}
}
console.log(Student)
let s1 = new Student()
console.log(s1.say);
console.log(s1.sayHello);
结论:继承的时候会执行构造器,并且改变this指向为子类。挂在static上的属性和方法不被继承
ES6 要求,子类的构造函数必须执行一次 super 函数,否则会报错。不执行的话子类没有自己的this
子类super执行 :父类.prototype.constructor.call(this, props)`