JS对象创建与继承

对象创建

1. 字面量(复用性差)
	const student = {
		name: 'name'
		school: 'school',
		teacher: 'teacher'
	}
2. Object 创建(复用性差)
	const student = new Object()
	student.name =  'name'
	student.school = 'school'
	student.teacher = 'teacher'
3. 工厂模式(对象身份识别不了,都是由Object创建)
	function Student(name, school, teacher){
		const obj = new Object()
		obj.name = name
		obj.school = school
		obj.techer = teacher
	}
4. 构造函数(方法创建重复)
	function Student(name, school, teacher){
		this.name = name
		this.school = school
		this.teacher = teacher
		this.say = function(){
			console.log(this.name)
		}
	}
5. 构造函数+原型

较好的解决了以上问题,使用最为广泛,美中不足,定义的属性方法分离,封装性不强。

	function Student(name, school, teacher){
		this.name = name
		this.school = school
		this.teacher = teacher
	}
	Student.prototype.say = function(){
		console.log(this.name)
	}
6. 动态原型

动态原型方式创建实例方法就是在第一次使用时创建,之后再实例化时不会重复创建

	function Student(name, school, teacher){
		this.name = name
		this.school = school
		this.teacher = teacher
		if(typeof this.say !== 'function'){
			Student.prototype.say = function(){
				console.log(this.name)
			}
		}
	}

对象继承

对象继承的方法核心是原型链。

1. 原型链继承
	function Teacher(){
		this.name = 'teacher'
	}
	Teacher.prototype.say = function(){
		console.log('i am a teacher')
	}
	function Student(){}
	Student.prototype = new Teacher()
	let stu = new Student()
	stu.say()  // i am a teacher

让Student的原型指向Teacher的实例对象,基于原型链的特性,可进一步继承到Teacher.prototype上的方法。
问题:引用类型的数据会被子类共享,无法向父类传递参数。

2. 盗用构造函数继承
	function Teacher(){
		this.hobby = {
			sport: 'basketball',
			subject: 'subject'
		}
	}
	function Student(){
		Teacher.call(this)
	}
	let s1 = new Student(),
		s2 = new Studnet()
	s1.hobby.book = 'book'
	console.log(s1,s2)  // 只有s1发生了变化

这种构造方式的目的是让每子类个实例之间屏蔽引用类型数据共享。
原理:父类的this指向子类,子类中也就能继承父类实例的属性和方法,call方法也解决了向父类传递参数的不足。
问题:无法得到父类原型上的方法。

3. 组合继承
	function Teacher(){
		this.name = 'name'
	}
	Teacher.prototype.say = function(){
		console.log(this.name)
	}
	function Student(){
		Teacher.call(this)
	}
	Student.prototype = new Teacher()
	let s1 = new Student(),
		s2 = new Student()
	console.log(s1,s2)

将前两种继承方式组合,延续了它们的优势。
问题:重复调用父类,newcall。由于直接改写子类的原型为父类的实例,所以父类实例上的属性和方法会重复出现。

4. 原型式继承
	function createObj(obj){
		function F(){}
		F.prototype = obj
		return new F()
	}

类似于创建对象原型,简单方便使用。
问题:还是会出现引用类型数据共享的问题,类似于一。

5. 寄生式继承
	function extendObj(obj){
		let newObj = createObj(obj)
		newObj.say = function(){
			console.log('this is a new Obj')
		}
		return newObj
	}

在原型式继承的基础增强对象,提供了可用的方法。
问题:引用类型的数据共享,不能向父类传参。

6. 寄生式组合继承
	function Teacher(){
		this.name = 'name'
	}
	function Student(){
		Teacher.call(this)
	}
	function inheritProto(target, origin){
		let prototype = createObj(origin.prototype)
		prototype.constructor = target
		target.prototype = prototype
	}
	inheritProto(Student, Teacher)
	// 或者用 Object.create()

原理:直接将子类的原型继承父类的原型。
避免了父类的重复调用,属性方法重复创建。
注意:若在继承前在子类的原型上添加方法会被覆盖,使用时最好在继承后增加方法。
ES6中官方也引入新的继承方法 extends

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值