27(继承)

文章目录

一:原型继承

1·1:原型继承的定义

所谓原型继承:就是子类自动的拥有父类的属性和方法,继承可以提高代码的复用性,并且子类可以添加新的属性和方法

继承:让原型对象的值,等于另一个类型的实例,即实现了继承

原型链:一个原型对象指向另一个实例,以此类推,就会构成一个原型链

原型继承:
	function animal(name, age) {
		this.name = name;
		this.age = age;
	}
	animal.prototype.eat = function() {
		console.log(this.age+"岁的"+this.name+ "吃香蕉")
	}
//继承的核心语句
	monkey.prototype = new animal("大猩猩",20);
	
	function monkey(color){
		this.color=color
	}
	monkey.prototype.behaiour=function(){
		console.log("行为")
	}
	let m=new monkey("嘿黑");
	// m.name="猴子";
	// m.age=30;
	console.log(m.name,m.age,m.color);
	m.eat();
	m.behaiour()

1·2:原型继承的注意事项

  • 必须先要定义原型继承关系,在对子类的自定义属性和方法进行添加

  • 继承关系实现后,不能再修改子类的prototype的数值

  • 父类里包括引用类型的属性的时候,它会被所有实例共享其值

  • 子类实例化对象由父类继承的属性,无法进行初始化

function Animal(name){
		this.name = name;
	}

	Animal.prototype.eat = function(){
		console.log("动物用来吃饭");
	}
	
	function Human(id){
		this.id = id;
	}

Human.prototype = new Animal("老王");
	
	Human.prototype.makeTools = function(){
		 console.log("人可以制作工具");
	}
	let h = new Human(6);//new Human("小明",9);
	console.log(h.name,h.id);
	h.eat();
	h.makeTools();
	
	let h1 = new Human(16);//new Human("大明",19);
	console.log(h1.name,h1.id);

console.log(h instanceof Human )

1·3:instanceof:

判断某一个对象是否为某一个类,返回一个boolean值

对象 instanceof 类

二:深拷贝与浅拷贝

2·1:拷贝的定义

拷贝:用已有的一个变量去初始化另一个变量(拷贝只发生在引用数据类型中)

浅拷贝:传参时值只传递了引用空间的地址

深拷贝:开辟空间,且赋值

深拷贝:

	function Student(id){
		this.id = id;
	}
	
	Student.prototype.clone = function(){
		//temp存着new出来的堆的空间址
		let temp = new Student(this.id);
		return temp;
	}
	
	//深拷贝:开辟空间且赋值
	let s1 = new Student(1);
	//给s2返回一个堆空间的地址,且用s1的数值,初始化这个堆空间
	let s2 = s1.clone();
						
	s2.id = 456;
 console.log(s1.id,s2.id);
	
浅拷贝:
 function Student(id){
	 	this.id = id;
	 }
	
	 let s1 = new Student(1);
	 let s2 = s1;//浅拷贝
	 //只拷贝了地址,但是并未开辟空间,等价于配了把钥匙
	 s2.id = 7;
	
	 console.log(s1.id);

三:call和apply的继承

3·1:常规使用

  • 解决了原型继承无法在初始化时,修改父类派生的属性
function Animal(name,id){
		this.name = name;
		this.id = id;
	}
	
	function Student(name,id,score){
		//借用父类的构造方法
		//接收"父类"的属性
		Animal.call(this,name,id);
		//新添加的属性
		this.score = score;
	}
	
	let s = new Student("老王",16,100);
	console.log(s.name,s.id,s.score);
	
	let s1 = new Student("小明",26,100);
	console.log(s1.name,s1.id,s.score);
	
	s1.eat();

3·2:call和apply使用的缺陷

  • 无法继承父类原型上的属性和方法
  • 单独使用这种借用的模式,所有要继承的属性和方法都要在父类型的构造函数里定义,特别是实例共享的属性和方法也写在构造函数里,那么这样会浪费内存

四:混合继承

4·1:常规使用

结合前两种方式

  • apply与call继承属性
  • 原型对象prototype继承方法
function Animal(name,id){
		this.name = name;
		this.id = id;
	}
	
	Animal.prototype.eat = function(){
		console.log("Animal eat");
	}
	
	function Human(name,id,score){
		Animal.apply(this,[name,id]);
		this.score = score;
	}
	
	Human.prototype = new Animal();
	
	Human.prototype.study = function(){
		console.log("Human study");
	}
	
	let h = new Human("老王",1,100);
	console.log(h.name,h.id,h.score);
	h.eat();
	h.study();

五:ES6的继承

class Animal{
		constructor(name,id) {
		    this.name = name;
			this.id = id;
		}
		
		//等价于绑定在原型对象上的方法
		eat(){
			console.log("Animal eat");
		}
	}
	
	//extends继承的关键字
	class Student extends Animal{
		constructor(name,id,score) {
		    //借用父类的构造方法必须用super关键字
			super(name,id);
			this.score = score;
		}
		
		study(){
			console.log("Student study");
		}
	}
	
	let s = new Student("laowang",66,100);
	
	console.log(s.name,s.id,s.score);
	
	s.eat();
	s.study();
	

六:多态

多态:发出一个消息,不同的对象实现不同的消息响应

  • call(对象,该函数的真正参数1,参数2…);
  • apply(对象,[参数1,参数2…]);
function Monkey(name){
		this.name = name;
	}

	function Snake(name){
		this.name = name;
	}

	//实现不同类型对象  吃的行为
	function eat(food1,food2){
		console.log(this.name + ":" + food1 + "," + food2);
	}
	
	let m = new Monkey("金刚");
	let s = new Snake("美杜莎");
	
	eat.call(m,"香蕉","草莓");
	eat.call(s,"许仙","皮卡丘");
	
	eat.apply(m,["车厘子","煎饼"]);
	eat.apply(s,["大蛇丸","皮卡丘"]);
function eat(food1,food2){
	console.log(this.name + ":" + food1 + "," + food2);
}

let m = new Monkey("金刚");
let s = new Snake("美杜莎");

eat.call(m,"香蕉","草莓");
eat.call(s,"许仙","皮卡丘");

eat.apply(m,["车厘子","煎饼"]);
eat.apply(s,["大蛇丸","皮卡丘"]);

上一篇:英语入门学习笔记(一)


下一篇:了解代理模式,以及jdk的代理模式与cglib的代理模式的区别