javascript中的继承

         在看《javascript精粹》这本书时,继承这个章节看得有些迷糊,和《JavaScript高级程序设计》中的思路差异比较大,于是回头看了一下《JavaScript高级程序设计》,安慰一下受伤的智商,总结一下,《javascript精粹》真的需要反复看很多遍。之后看明白了再来比较一下两本书内容的差别。

1. 原型链继承
        原型链继承的本质就是将一个类型的实例赋给另一个类型的原型实现的

function SuperType(){
	this.property = true
}
SuperType.prototype.getSuperValue = function(){
	return this.property
}
function SubType(){
	this.subproperty = false
}
SubType.prototype = new SuperType()
SubType.prototype.getSubValue = function(){
	return this.subproperty
}
var instance = new SubType()

       在这里,我们给SubType换了一个全新的原型,里边包括SuperType的全部属性和方法,内部还有一个指针,指向了SuperType的原型。instance作为subType的实例,对于它其中的属性和方法的调用就和原型的搜索机制一样了,依次向上搜索,如果调用了getSuperValue方法,首先会搜索实例,其次是SubType,最后是SuperType。此外,任何的函数都有一个指向Object原型的指针,这个就不在刚才的搜索链里边了,属于另一个继承层次。原型链继承存在的问题包含引用类型值的原型属性会被所有实例共享。因为原型省略了构造函数初始化传递参数这一环节,所有的实例在默认情况下都取得了相同的属性值,这里其实也是原型最大问题的体现,是有原型共享的本性导致的。由于SubType继承了SuperType,所以colors属性存在于SubType的prototype中,所以对于SubType的子孙来说,colors只有父类原型当中的一个。

function SuperType(){
	this.colors = [red,blue]
}
function SubType(){}
SubType.prototype = new SuperType()
var instance1 = new SubType()
instance1.colors.push('yellow')
var instance2 = new SubType()
console.log(instance1.colors)//red blue yellow
console.log(instance2.colors)//red blue yellow

        可以看到,这里只在instance1中push了一个值,instance2实例中并没有对colors进行操作,但两个实例的属性值是一样的,这就是使用原型链继承存在的第一个问题。另外一个,就是不能在不影响其他实例的情况下向超类中传递参数。鉴于以上两个问题,实际时单独应用原型链的时候很少。

       “包含引用类型值的原型属性会被所有实例共享”,我对这句话的理解是,经过subType对supertType的原型继承,在subType实例使用colors时,colors是存在于subType原型中的,所以它会被共享。书中有些话一开始不理解,经过反复阅读,自己总结下来,对于原型的有了进一步的认识。

2. 借用构造函数

思想:在子类型的构造函数中调用超类型构造函数。

function SuperType(){
	this.colors = ['red','blue']
}
function SubType(){
	SuperType.call(this)
}

借用构造函数的优点是可以传递参数,比如:

function SuperType(name){
	this.name = name
}
function SubType(){
	SuperType.call(this,'haha')
}


但是这种方法也是存在问题的,比如超类原型中存在的方法和属性我们就获取不到了,只能获取到构造函数中的属性和方法。

3. 组合继承

        思想:将原型链继承和借用构造函数继承结合在一起,即借用原型链实现对原型属性和方法的继承,借用构造函数实现对实例属性的继承。

function SuperType(name){
	this.name = name
	this.colors = ['red','blue'] 
}
SubType.prototype.sayName = function(){alert(this.name)}
function SubType(name,age){
	SuperType.call(this,name)
	this.age = age
}
SubType.prototype = new SuperType()
SubType.prototype.constructor = SubType
SubType.prototype.sayAge = function(){alert(this.age)}

var instance1 = new SubType('ha',13)
instance1.colors.push('yellow')
instance1.sayName()//'ha'
console.log(instance1.colors) //'red,blue,yellow'
var instance2 = new SubType('haha',131)
instance2.sayName()//'haha'
console.log(instance1.colors) //'red,blue'
这样其实是有两组name和color属性的,一组在SubType原型中,另一组通过SubType实例化得出,经过实例化得出属性就覆盖掉了SubType原型当中的属性。组合式继承巧妙的解决了原型链继承中引用类型值原型属性和借用构造函树继承中的无法获取超类方法和属性的问题,成为最常用的继承模式。

4. 原型式继承

这种方法并没有上述方法中的构造函数,而是基于一个已有的对象,利用Object的create方法(ES5),将这个已有的对象作为原型,创建新对象的过程。

create方法接受两个参数,第一个是已有对象,第二个是新对象的特有属性。

var person = {
	name : 'haha',
	friends : ['a','b']
}
var newPerson1 = Object.create(person,{name:{
	value : 'heihei'
}})
var newPerson2 = Object.create(person,{name:{
	value : 'hehe'
}})
console.log(newPerson1.name)  //heihei
console.log(newPerson2.name)   //hehe
newPerson1.friends.push('c')  
console.log(newPerson1.friends)   //['a','b','c']
console.log(newPerson2.friends)   //['a','b','c']
可以看到,使用这种方法可以快速的创建具有类似属性的对象,同时又可以针对特有的属性值进行分别设置,同时省去了创建一些构造函数的麻烦,在合适的情况下效率是比较高的,关键词是对象相似。

5. 寄生式继承

思路:构建一个封装了继承过程的函数,传入一个原有对象,在函数内部根据传入的对象创建一个新对象并赋予新对象新的方法。

function createAnother(original){
	var clone = object(original)   //object一个返回新对象的函数
	clone.sayHi = function(){}
	return clone
}

和原型式继承一样,这里不需要构造函数和自定义类型,只要传入一个已存在的对象即可。

6. 寄生组合式继承

组合继承中在继承超类构造函数属性和超类原型方法时调用了两次超类构造函数,寄生组合式继承将第二次调用超类构造函数给省去了。具体方法就是创建一个接收子类和超类构造函数的函数,在其中修改子类的prototype,实现对超类方法的继承。

function inheritPrototype(SubType,SuperType){
	var prototype = Object(SuperType.prototype)
	prototype.constructor = SubType
	SubType.prototype = prototype
}
function SuperType(name){
	this.name = name
	this.colors = ['red','blue'] 
}
function SubType(name,age){
	SuperType.call(this,name)
}
// SubType.prototype = new SuperType()
inheritPrototype(SubType,SuperType)




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
资源包主要包含以下内容: ASP项目源码:每个资源包都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值