javascript快速学习三:javascript实现继承的与众不同方式
我们知道了JavaScript中没有类的概念,但是可以使用构造器函数实现来替代。有封装吗?有,对象本身就包括数据及数据的相关行为方法。有聚合吗?有,一个对象可以包含其他对象。然后这一篇讨论一下另一个面向对象的概念,继承。
javaScript是一种动态的程序语言,因而他对于同一个任务往往会有几种不同的解决方案,在继承问题上也不例外。
原型链
默认的继承模式是通过原型来实现继承关系链。根据之前我们了解的,JavaScript中每个函数都有一个名为Prototype的对象属性,该函数在呗New操作符调用时会创建出一个对象,并且该对象会有一个指向其原型对象的秘密链接。通过该链接(命名为:_proto_)我们可以在新建的对象中调用相关原型对象的方法和属性。这就是我们所说的“原型链”。
代码:
施展继承:
由于JavaScript与我们熟悉的其他程序语言不太一样,是一种完全依靠对象的语言,没有Class的概念。于是我们需要New Shape()构造一个实体,并通过该实体属性完成相关继承工作,而不是直接继承Shape(),这也确保了在继承实现之后,我们对Shape()的任何修改重写甚至删除,都不会对TwoDShape()产生影响,因为我们继承的是由该构造器所创建的一个对象实体。
测试一下:
我们最后显示出来的值,实际上是调用了Shape()中的ToString()方法,是靠继承联系过来的。
我们看一下,在使用过程当中JavaScript做了哪些事情:
- 首先,遍历My对象中所有属性,但没有找到toString()的方法。
- 接着再去查看my._proto_所指向的对象,该继承链是在执行new TwoDShape()时创建的。
- 显然在遍历TwoDShape()时也找不到ToString()方法。
- 终于在New Shape()中找到了toString()方法。
- 最后,该方法被调用。
将共享属性迁移到原型中去
当我们用某一个构造器创建对象时,其属性被添加到this中去,这会使得某些不能通过实体改变属性出现一些效率低下的情况。如上面的例子,我们用new Shape()新创建对象时,每个实体都会有一个全新的Name属性,并在内存中拥有自己的独立空间。事实上,我们可以选择将name属性添加到所有实例共享的原型对象中去。如:
function Shape(){}
Shape.prototype.name=‘shape‘;
这样一来我们每次new Shape()时,就不会创建只属于自己的属性了,而是将其添加到了该对象的共享原型中去。
这样我们将之前认为会重新在对象new时会创建独立空间的属性通过这种方式,就回有效的提高效率。但是针对于new Triangle()所创建上却又不同,因为它接受两个参数,只能是保持自身独有,但是他的getArea()方法却是可以共享的。
临时构造器--new F();
由于所有属性都指向了父对象,父对象的属性就回受到影响,要解决这种依赖连锁,我们可以通过临时构造器充当中介进行解耦。
我们可以创建new F(),并将其原型设置为父级构造器。
也就是相当与我们在两个需要继承的对象之间新建一个临时的代理,通过操作代理对象,也可以实现一些父对象不包含的属性。
uber--子对象访问父对象的方式
在面向对象的语言当中我们通常会有子对象访问父对象的方式,C#中用的Base,其他语言有的用Super。在JavaScript中引入了一个uber的属性实现,只要令其指向父对象原型即可。
将继承封装成函数
既然我们已经掌握了JavaScript中实现继承的一些方法,我们就需要将这些组织起来用一种更好的方式方便我们使用,聪明的程序员们总是用他们懒惰的思想,改变着代码世界,Jquery的作者封装了JavaScript中常见的方法及dom操作等,在一定程度上促进了JavaScript焕发第二春。
我们通过我们掌握的继承只是创建一个extend()函数,便于我们重用。
上面的这个继承封装智慧,是YUI库在实现继承关系时采用的方法,通过封装大大较少了代码量,同时使得实现也更加的优雅。其实程序员的智慧与价值更多的是通过老瓶装新酒的方式是程序更加适应时代的发展时代的要求,那些抱着老技术而又怨天尤人的人,是能说他们自己放弃了自己。
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。