原型链与常用继承方法

原型链:当访问一个对象的属性时,如果该对象内部不存在这个属性,就会去该对象的__proto__ 上(也就是它构造函数的prototype)查找 。该构造函数的prototype上也有一个自己的__proto__ 属性,然后继续向上查找, 直到__proto__为null,就停止查找。

let date = new Date()
console.log(date.__proto__ === Date.prototype); //true
console.log(date.__proto__.constructor === Date); //true
console.log(date.__proto__.__proto__ === Date.prototype.__proto__); //true
console.log(Date.prototype.__proto__.constructor === Object); //true
console.log(Date.prototype.__proto__ === Object.prototype); //true
console.log(Object.prototype.__proto__ === null); //true

封装:将公用的方法或者组件进行封装,达到代码复用,让我们的代码更简洁
继承:子类继承父类中的实例和方法
多态:不同对象作用于同一操作产生不同的效果

1.原型链继承

特点:继承父类原型上的属性和方法。
缺点:创建子类实例时,不能向父类构造函数中传参数,无法实现多继承

//父类
function Person(name) {
     this.name = name;
 	 this.sleep = function(){
    	console.log(this.name + '正在睡觉')
   }
}
Person.prototype.change = "123木头人"
Person.prototype.sayHi = function () {
     console.log("您好啊!");
};
//子类
function Child(age) {
     this.age = age
}
Child.prototype = new Person()
Child.prototype.constructor = Child
let child = new Child(10)
console.dir(child)

原型链继承

2.构造函数继承

特点:解决了子类构造函数向父类构造函数中传递参数,可以实现多继承(call或者apply多个父类)
缺点:方法都在构造函数中定义,无法复用,不能继承原型上的属性和方法

//父类
function Person(name) {
     this.name = name;
 	 this.sleep = function(){
    	console.log(this.name + '正在睡觉')
   }
}
Person.prototype.change = "123木头人"
Person.prototype.sayHi = function () {
     console.log("您好啊!");
};
//子类
function Child(name,age) {
	Person.call(this, name) 
 // Person.apply(this, [name]) //=> apply后面的参数是个数组.
	this.age = age;
}
let child = new Child("校长",10)
console.dir(child)

构造函数继承

3.组合继承

特点:把1和2的方法相结合,函数可以复用,可以继承属性和方法,并且可以继承原型的属性和方法
缺点:会挂载两次父类的属性和方法(有两个name和sleep),产生小bug,

//父类
function Person(name) {
     this.name = name;
 	 this.sleep = function(){
    	console.log(this.name + '正在睡觉')
   }
}
Person.prototype.change = "123木头人"
Person.prototype.sayHi = function () {
     console.log("您好啊!");
};
//子类
function Child(name,age) {
	Person.call(this, name) 
 // Person.apply(this, [name]) //=> apply后面的参数是个数组.
	this.age = age;
}
Child.prototype = new Person()
Child.prototype.constructor = Child
let child = new Child("校长",10)
console.dir(child)

组合继承

4.寄生组合继承

特点:通过寄生的方式来修复组合式继承的不足,完美的实现继承。
Object.create()方法创建一个空对象,让属性和方法继承到对象的__proto__上

//父类
function Person(name) {
     this.name = name;
 	 this.sleep = function(){
    	console.log(this.name + '正在睡觉')
   }
}
Person.prototype.change = "123木头人"
Person.prototype.sayHi = function () {
     console.log("您好啊!");
};
//子类
function Child(name,age) {
	Person.call(this, name) 
 // Person.apply(this, [name]) //=> apply后面的参数是个数组.
	this.age = age;
}
Child.prototype = Object.create(Person.prototype)
Child.prototype.constructor = Child
let child = new Child("校长",10)
console.dir(child)

寄生组合继承

5.ES6 class extend继承

//class 相当于es5中构造函数
//class中定义方法时,前后不能加function,全部定义在class的protopyte属性中
//class中定义的所有方法是不可枚举的
//class中只能定义方法,不能定义对象,变量等
//class和方法内默认都是严格模式
//es5中constructor为隐式属性
class People {
    constructor(name, age) {
        this.name = name;
        this.age = age;
    }
    sleep() {
        console.log(`${this.name} ${this.age} 正在睡觉`)
    }
}
//继承父类
class Child extends People {
    constructor(name, age) {
        //继承父类属性
        super(name, age);
    }
    sleep() {
        console.log(this);
        //继承父类方法
        super.sleep()
    }
} 
let child = new Child('小红',18); 
console.log(child);
child.sleep();    //小红 18 正在睡觉

总结:ES5继承和ES6继承的区别

ES5的继承实质上是先创建子类的实例对象,然后再将父类的方法添加到this上(Parent.call(this)).
ES6的继承有所不同,实质上是先创建父类的实例对象this,然后再用子类的构造函数修改this。因为子类没有自己的this对象,所以必须先调用父类的super()方法,否则新建实例报错。

  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值