本文主要介绍在js中实现继承的五种方法,帮助你更好的理解和使用JavaScript。感兴趣的朋友可以了解一下。
借用的构造函数
这项技术的基本思想很简单,就是在子类型构造函数内部调用超类型构造函数。此外,函数只是在特定环境中执行代码的对象,因此也可以通过使用apply()和call()方法在新创建的对象上执行构造函数。
功能框(名称){
this.name=name
}
Box.prototype.age=18岁
职能部门(名称){
Box.call(this,name) //对象模拟,只能继承结构中的信息。
}
var办公桌=新办公桌(“ccc”)
控制台. log(桌面.名称)//- ccc
console.log(desk.age) //-未定义
可以看到,只有实例属性被继承,原型上的属性是不可访问的。这个模型解决了两个问题,就是可以传承,但是没有原型,就没有办法复用。
组合继承
功能框(名称){
this.name=name
}
Box.prototype.run=function (){
Console.log(this.name 正在运行.)
}
职能部门(名称){
Box.call(this,name) //对象模拟
}
Desk.prototype=new Box() //原型链
var办公桌=新办公桌(“ccc”)
控制台. log(桌面.名称)//- ccc
Desk.run() //- ccc正在运行.
这种继承方式的思路是用原型链继承原型属性和方法,借用构造函数继承实例属性。
原型继承
原型继承:在原型的帮助下,可以基于现有对象创建新的对象,而不必创建自定义类型。在这一点上,必须提到一个人。道格拉斯克洛克福特在2006年写的一篇文章《Prototype inheritance in Javascript》(JavaScript中的原型继承)中给出了一个方法:
函数对象(o) {//传递一个文字函数
函数F(){ }///创建一个构造函数
f .原型=o;//将文本函数赋给构造函数的原型
Return new F() //最后,返回实例化的构造函数
}
请看下面的例子:
函数obj(o) {
函数F (){}
f .原型=o;
返回新的F()
}
var box={
名称: ccc ,
年龄:18,
家庭:[兄弟,姐妹]
}
var box1=obj(box)
console.log(box1.name) //- ccc
1.box1.family.push(姐姐)
Console.log (box1.family)//-[兄弟,姐妹,姐妹]
var box2=obj(box)
Console.log (box2.family)//-[兄弟,姐妹,姐妹]
因为上面代码的实现逻辑非常类似于原型链继承,所以引用数组也就是family属性是共享的。
寄生式继承
函数obj(o) {
函数F (){}
f .原型=o;
返回新的F()
}
函数create(o){
var=obj(o)//通过调用函数创建一个新对象
Clone.sayName=function(){ //以某种方式增强此对象
console.log(hi )
}
返回克隆//返回此对象
}
var person={
名称: ccc ,
朋友:[aa , bb]
}
var anotherPerson=创建(人员)
anotherPerson.sayName() //-嗨
此示例中的代码基于Person返回一个新对象————anotherPerson。新对象不仅拥有person的所有属性和方法,还拥有自己的sayHi()方法。当主要考虑对象而不是自定义类型和构造函数时,寄生继承也是一种有用的模式。用寄生继承给对象添加函数会因为不能重用函数而降低效率,类似于构造函数模式。
寄生组合遗传
如前所述,组合继承是Javascript最常用的继承方式,但它也有自己的缺点。继承的最大问题是超类型构造函数在任何情况下都会被调用两次:一次是在创建子类型原型时,另一次是在子类型构造函数内部。是的,子类型最终将包含父类型对象的所有实例属性,但是我们必须在调用子类型构造函数时重写这些属性。让我们看看下面的例子:
函数超类型(名称){
this.name=name
this.colors=[red , black]
}
supertype . prototype . say name=function(){
console.log(this.name)
}
函数子类型(姓名、年龄){
SuperType.call(this,name) //再次调用SuperType
this.age=年龄
}
subtype . prototype=New SuperType()//第一次调用超类型
子类型.原型.构造函数=子类型
subtype . prototype . sayage=function(){
console.log(this.age)
}
第一次调用超类型构造函数时,SubType.prototype将获得两个属性:name和colors。都是超类型的实例属性,但是现在在子类型的原型中。当调用子类型构造函数时,将再次调用超类型构造函数,这一次实例属性name和colors是在新对象上创建的。因此,这两个属性屏蔽了原型中同名的两个属性。也就是说,有两组名称和颜色属性:一组在实例上,另一组在原型上。这是两次调用超类型构造函数的结果。解决这个问题的方法是————寄生组合遗传。
所谓寄生组合继承,就是属性通过借用构造函数来继承,方法通过原型链的混合形式来继承。其背后的基本思想是:不需要为了制作子类型的原型而调用超类型的构造函数,我们需要的只是超类型原型的一个副本。本质上,我们使用寄生继承来继承超类型的原型,然后将结果赋给子类型的原型。寄生组合遗传的基本模式如下:
函数对象(o) {
函数F (){}
f .原型=o;
返回新的F()
}
函数inheritPtototype(子类型,超类型){
var prototype=object(supertype . prototype)//创建对象
prototype . constructor=subtype//增强对象
SubType.prototype=prototype //指定对象
}
函数超类型(名称){
this.name=name
this.colors=[red , white]
}
supertype . prototype . say name=function(){
console.log(this.name)
}
函数子类型(姓名、年龄){
SuperType.call(this,name)
this.age=年龄
}
inheritPtototype(子类型,超类型)
subtype . prototype . sayage=function(){
console.log(this.age)
}
var instance=新的子类型(“ccc”,18)
instance.sayName() //- ccc
instance.sayAge() //- 18
console.log(实例)
控制台打印的结构:
以下内容的详细说明:
这个例子的高效之处在于它调用了一次超类型构造函数,从而避免了在SubType.prototype上创建不必要的、多余的属性,同时原型链可以保持不变;所以instanceof和isPrototypeOf()也可以正常使用。这也是很多大厂采用的传承方式。
这就是在js中实现继承的五种方法的细节。关于js实现继承的更多信息,请关注我们的其他相关文章!