JS实现继承

1、通过原型链继承

让一个构造函数的原型是另一个类型的实例,那么这个构造函数new出来的实例就具有该实例的属性
缺点:对象实例共享所有继承的属性和方法。无法向父类构造函数传参

/*
让一个构造函数的原型是另一个类型的实例,
那么这个构造函数new出来的实例就具有该实例的属性
*/
	function Student3(id,name){
		this.id = id,
		this.name = name,
		this.sayhi = function(){
			console.log("我叫"+this.name+",id是"+this.id)
		} // 静态方法
	}
	//prototype称为原型,类似java里的static
	// Student3.prototype.count =100;  //原型变量  -- java里叫静态变量
	Student3.prototype.study = function(){
		console.log("共享学习空间")
	} 
	
	function Student( ){}
	//让一个构造函数的原型是另一个类型的实例,那么这个构造函数new出来的实例就具有该实例的属性
	Student.prototype = new Student3(); //Student 子类, Student3 父类
	let student2 = new Student();
	student2.id = 10;
	student2.name = "张三";
	student2.sayhi();
	student2.study()
	//结果	我叫张三,id是10    共享学习空间

	//缺点:对象实例共享所有继承的属性和方法。无法向父类构造函数传参

2、借用构造函数继承

在子类构造函数的内部调用父类的构造函数,使用apply()或call()方法将父对象的构造函数绑定到子对象上

优点:解决了原型链实现继承不能传参的问题和父类的原型共享的问题

缺点:借用构造函数的缺点是方法都在构造函数中定义,无法实现函数复用。在父类型中定义的方法,对于子类型而言是不可见的,结果所有类型都只能使用构造函数模式

/*
在子类构造函数的内部调用父类的构造函数,
使用apply()或call()方法将父对象的构造函数绑定到子对象上
*/
//父类构造函数
	function Student3(gender){
			
		this.info = {
			id :12,
			name :"李四",
			age: 13,
			gender: gender		
		}
	}
	//子类
		function Student(gender) {
			Student3.call(this,gender);
			// Student3.apply(this,id);
		}
		let student2 = new Student('男');
		student2.info.phone = '124263673'
		console.log(student2.info);//{id: 12, name: '李四', age: 13, gender: '男', phone: '124263673'}
		
		//优点:解决了原型链实现继承不能传参的问题和父类的原型共享的问题
		//缺点:借用构造函数的缺点是方法都在构造函数中定义,无法实现函数复用。
		  // 在父类型中定义的方法,对于子类型而言是不可见的,结果所有类型都只能使用构造函数模式
		

3、组合式继承

将原型链和借用构造函数来实现对实例属性的继承.这样,既通过在原型上定义方法实现了函数复用, 又保证在每个实例都有自己的属性

优点:解决了原型链继承和借用构造函数继承造成的影响

缺点:无论什么情况下,都会调用两次父类构造函数:一次是在创建子类原型的时候,另一次是在子类构造函数内部

		//3组合式继承
		// 将原型链和借用构造函数来实现对实例属性的继承.这样,既通过在原型上定义方法实现了函数复用,
		// 又保证在每个实例都有自己的属性
		
		// 父类
		function Student3(gender){
			console.log('执行次数');
			this.info = {
				id :12,
				name :"李四",
				age: 13,
				gender: gender		
			}
		}
		Student3.prototype.study = function(){  //使用原型链继承原型上的属性和方法
			console.log(this.info.id,this.info.name,this.info.age)
		}
		
			function Student(gender) {
			  	Student3.call(this,gender);  //使用构造函数传递参数
			}
			
			Student.prototype = new Student3();  
			
			let student2 = new Student("男");
			
			student2.info.phone  = "62566273562"
			
			student2.study()
			console.log(student2.info)
			//结果 
					/* 执行次数  
					执行次数  
					12 '李四' 13 
					{id: 12, name: '李四', age: 13, gender: '男', phone: '62566273562'} */

//优点:解决了原型链继承和借用构造函数继承造成的影响
/*缺点:无论什么情况下,都会调用两次父类构造函数:
一次是在创建子类原型的时候,另一次是在子类构造函数内部*

4、ES6的class类继承

子类必须在constructor方法中调用super方法,因为子类没有自己的this对象,而是继承父类的this对象,然后对其进行加工。如果不调用super方法,子类就得不到this对象。

优点:语法简单。操作方便
缺点:不是所有浏览器都支持class关键字

//Class通过extends关键字实现继承,其实质是先创造出父类的this对象,然后用子类的构造函数修改this
		//子类的构造函数中必须调用super()方法,且只有在调用了super()之后才能使用this,
		//因为子类的this对象是继承父类的this对象,然后对其加工,而super()方法表示的是父类的构造函数,用来新建父类的this对象
		
		//父类	
		class Student3{
			//方法
			constructor(id,name){
				this.id = id
				this.name = name
			}
			//方法
			getkind(){
				return '学号:'+ this.id+',姓名:'+this.name
				// return this.kind
			}
		}
		//子类
		class Student extends Student3{
			constructor(phone){
				super(12,'张三');
				this.phone = phone;
				
			}
			info(){
				console.log( super.getkind()+',电话:'+this.phone);
			}
		}	
			let student2 = new Student('23676381');
			student2.info();
  • 8
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

安风\(`Δ’)/

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值