JS-面向对象编程(继承)

196 阅读3分钟

原型链继承

function Animal(){
    this.name = 'aaa';
}
Animal.prototype.getName = function(){
    return this.name;
}
function Dog(){};
//Dog继承了Animal
//本质:重写原型对象,将一个父对象的属性和方法作为一个子对象的原型对象的属性和方法
Dog.prototype = new Animal();
Dog.prototype.constructor = Dog;
var d1 = new Dog();
console.log(d1.name);//aaa
console.log(d1.getName());//aaa
console.log(d1.constructor);//Dog(){}

问题:父类中的实例属性一旦赋值给子类的原型属性,此时这些实例属于子例的共享属性;实例化子类型的时候,不能像父类型的构造函数传参

借用构造函数继承

//经典继承:在子类的构造函数内部调用父类的构造函数
//缺点:父类定义的共享方法不能被子类所继承下来
function Animal(name){
    this.name = name;
    this.color = ['red','green','blue'];
}
Animal.prototype.getName = function(){
    return this.name;
}
function Dog(name){
    //继承了Animal
    /*当new实例的时候,内部构造函数中this指向了d1,然后在当前构造函数内部
    再去通过call再去调用构造函数,那么父类中的沟站函数中的this指向的
    但是方法不能被继承下来*/
    Animal.call(this,name);
}
var d1 = new Dog('cokie');
var d2 = new Dog('bbb');
d1.color.push('purple');
console.log(d1.name);//cokie
console.log(d1.color);//["red", "green", "blue", "purple"]
console.log(d2.color);// ["red", "green", "blue"]
console.log(d1.getName());//getName is not a function

组合继承

			function Animal(name){
				this.name = name;
				this.color = ['red','green','blue'];
			}
			Animal.prototype.getName = function(){
				return this.name;
			}
			
			function Dog(name){
				//继承了Animal
				Animal.call(this,name);
			}
			//重写原型对象:把父类的共享方法继承下来
			Dog.prototype = new Animal();
			Dog.prototype.constructor = Dog;
			var d1 = new Dog('cokie');
			var d2 = new Dog('bbb');
			console.log(d1.getName());//cokie
			
			//问题:无论什么情况下,都会调用父类构造函数两次
			//1.一个是我们初始化子类的原型对象的时候
			//2.在子类构造函数内部调用父类的构造函数

寄生组合式继承

Dog.prototype = new Animal();
改成
Dog.prototype = Object.creat(Animal.prototype);

小结

  1. 原型链继承
    特点:重写子类的原型对象,父类原型对象上的属性和方法都会被子类继承
    问题:在父类中定义的实例医用类型的属性,一旦被修改,其他实例也会被修改。当实例化子类的时候,不能传递参数到父类
  2. 借用构造函数继承
    特点:在子类构造函数内部间接调用(call(),apply(),bind())父类函数
    原理:改变父类中的this指向
    优点:仅仅的是把父类中的实例属性当做子类的实例属性,并且能传参 缺点:父类中公有的方法不能被继承下来
  3. 组合继承
    特点:结合了原型链继承和借用构造函数继承的优点
    原型链继:公有的方法能被继承下来
    借用构造函数:实例属性能被子类继承下来
    缺点:调用了两次父类的构造函数
    1.实例化子类对象(这次不好)
    2.子类的构造函数内部(完美的)
  4. 寄生组合式继承
    var b = Object.creat(a)
    将a对象作为b实例的原型对象
    把子类的原型对象指向了父类的原型对象
    Dog.prototype = Object.creat(Animal.prototype)

    开发过程中是用最广泛的一种继承方式

多重继承

			//一个对象同时继承多个对象
			function Person(){
				this.name = 'person';
			}
			Person.prototype.sayName = function(){
				console.log(this.name);
			}
			//定制parent
			function Parent(){
				this.age = 30;
			}
			Parent.prototype.sayAge = function(){
				console.log(this.age);
			}
			
			function Me(){
				// 继承Person属性
				Person.call(this);
				Parent.call(this);
			}
			
			//继承方法
			Me.prototype = Object.create(Person.prototype);
			//不能重写原型对象
			// Me.prototype = Object.create(Parent.prototype);
			
			//Object.assign(targetObj,copyObj)
			Object.assign(Me.prototype,Parent.prototype);
			
			//指定构造函数
			Me.prototype.constructor = Me;
			var me = new Me();