这篇文章运用简单易懂的例子给大家介绍深入浅析js中的继承,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。
<强> js的“类”强>
javascript不像java、php等传统的OOP语言,js本身并没有类这个概念,那么它是怎么实现类的模拟呢?
- <李>构造函数方式李> <李>原型方式李> <>李混合方式李>
构造函数方式
函数Foo () { this.name=名字 这一点。像=function () { console.log (“$ {this.name}”) } } 让foo=new foo (& # 39; bibidong& # 39;)
像这样就是通过构造函数的方式来定义类,其实和普通函数一样,但为了和常规函数有个区分,一般把函数名首字母大写。
缺点:无法共享类的方法。
原型方式
函数Foo () {} Foo.prototype。颜色=& # 39;红色# 39; Foo.prototype。队列=(1、2、3) 让foo1=new Foo () 让foo2=new Foo () foo1.queue.push (4) console.log (foo1)//(1、2、3、4) console.log (foo2)//(1、2、3、4)
我们通过原型方式直接把属性和方法定义在了构造函数的原型对象上,实例可以共享这些属性和方法,解决了构造函数方式定义类的缺点。
缺点:可以看到我们改变了foo1的数据,结果foo2的队列属性也变了,这便是原型方式最大的问题,引用类型的属性会被其它实例修改。除此之外,这种方式下也无法传参。
<强>混合方式强>
函数Foo(){//属性定义在构造函数里面 this.name=名字 这一点。颜色=& # 39;红色# 39; 这一点。队列=(1、2、3) } Foo.prototype。像=function(){//方法定义在原型上 console.log (“$ {this.name}”) } 让foo1=new Foo () 让foo2=new Foo ()
所谓混合模式,便是把上面两种方式混合起来,我们在构造函数里面定义属性,在原型对象上定义要共享的方法,既能传参,也避免了原型模式的问题。
小结一下:js类的能力是模拟出来的,可以通过构造函数方式,原型方式来定义,混合模式则聚合了前两者的优点。除此,还有Object.create (), es6的类,都可以来创建对象,定义类。
<强>一、原型链继承强>
基于原型链查找的特点,我们将父类的实例作为子类的原型,这种继承方式便是原型链继承。
父函数(){ 这一点。颜色=& # 39;红色# 39; 这一点。队列=(1、2、3) } Parent.prototype。像=function () { console.log (& # 39; & # 39;) } 函数子(){} 的孩子。=新的父()//构造函数原型指针变了指向了父母 Child.prototype。构造函数=孩子//手动修复 让孩子=new ()
孩子。父的原型相当于是父类实例,父类父母的实例属性被挂到了子类的原型对象上面,拿颜色属性举个例子,相当于就是这样
Child.prototype。颜色=& # 39;红色# 39;
这样父类的实例属性都被共享了,我们打印一下的孩子,可以看到孩子没有自己的实例属性,它访问的是它的原型对象。
我们创建两个实例child1, child2
我们修改了child1的颜色属性,child2没有受到影响,并非是其它实例拥有独立的颜色属性,而是因为这个颜色属性直接添加到了child1上面,它原型上的颜色并没有动,所以其它实例不会受到影响从打印结果也可以清楚看到这一点。那如果我们修改的属性是个引用类型呢?
child1。队列=[1、2、3,& # 39;我被修改了& # 39;]//重新赋值 child1。像=function () {console.log(& # 39;像方法被我修改了& # 39;)} console.log (child1) console.log (child2)
我们重写了引用类型的队列属性和像方法,其实和修改颜色属性是完全一样的,它们都直接添加到了child1的实例属性上。从打印结果能看到这两个属性已经添加到了child1上了,而child2并不会受到影响,再来看下面这个。
child1.queue.push(& # 39;添加推动# 39;)//这次没有重新赋值 console.log (child1) console.log (child2)深入浅析js中的继承