深入探究JavaScript对象系列(六)
一.类和类型
在传统的面向对象的编程语言中,有很好的方法能够判断一个实例对象属于哪个类,但是在js中,并没有完美方法来实现这个功能,但是还是有几种方法来弥补,下面介绍3种:
a.instanceof运算符和isPrototype()方法,
instanceof操作符的左操作数是待检测其类的对象,右操作数是定义类的构造函数,如果o继承自c.prototype,则表达式 o instanceof c 返回true.,此外当o继承自一个也继承自c.prototype的对象时也会返回true;同样的isPrototype()方法也能实现类似功能,即在多个执行上下文场景中无法正常工作。
但是着两个都无法通过对象来获得类名,此外在客户端JavaScript中,出现多窗口和多框架子页面中兼容性不佳
b.constructor属性
这个属性在上一篇中刚刚提到过,用这个属性可以获得类名,但在多个执行上下文中的场景中也无法政策工作,而且并不是所有的对象中都具有这个属性。
c。使用构造函数的函数名
上述的两类方法在用来检测对象所属类中都有“多个执行上下文场景中无法正常工作”的问题,一种可能的解决方案是使用构造函数名称字符串,但是这样做在当构造函数没有名称的时候也无法正常工作。
二.鸭式辩型
鸭式辩型这个思考问题的方式是由James Riley提出的,它的思想是:像鸭子一样走路,游泳并且嘎嘎叫的鸟就是鸭子。
对于程序员来说:不要关注对象类型是什么,而是关注对象能做什么。拿上一篇中的例二来说,Range中的includes方法并没有对实参进行类型检测以确保它是数字类型,就直接拿来比较;此外在类数组对象中这点显得尤为明显,在很多场景虾,我们并不知道一个对象是否为数组对象,可以通过判断该对象是否包含一个length的属性,有就认为它是数组对象,即这只“鸭子”会游泳了,会不会走路和嘎嘎叫则不去判断。
鸭式辩型的实现方法让人感觉太“放任自流”:仅仅是假设输入的对象实现了必要的方法,没有进一步执行检查。如果输入对象没有遵循之前的“假设”,那么当代码试图调用那些根本不存在的方法时就会报错;另一种实现方法是对输入对象进行检查,但不是检查它们的类,而是用适合的名字来检查它们所实现的方法,这样可以将非法输入尽可能的拦截在前,并给出有效提示,请看下面的例子:
1 function quacks(o /*,...*/){ 2 for (var i = 1; i < arguments.length; i++) { 3 var arg = arguments[i]; 4 switch(typeof arg){ 5 case "string" : //直接用名字做检查 6 if(typeof o[arg] !== "function") return false; 7 continue; 8 case "function" : 9 arg = arg.prototype; 10 continue; 11 case "object": 12 for(var m in arg){ 13 if(typeof arg[m] !== "function") continue; 14 if(typeof o[m] !== "function") return false; 15 } 16 continue; 17 } 18 } 19 return true; 20 }
关于这个quacks函数有亮点需要注意:我们只是通过给定的名称来检测对象是否满足要求,但无法得知其细节,而这也正是鸭式辩型的本质所在;此外该函数该函数不能应用于内置类,因为内置类中的方法都是无法通过for/in来遍历的。
到此为止,算上之前5篇,再加上这一篇基本上以及把JavaScript中的面向对象的基础介绍完了,接下来会介绍些JavaScript中关于面向对象编程的技术,当然还是基于David Flanagan大神的那本《JavaScript权威指南》。
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。