JavaScript操作符instanceof揭秘
创始人
2024-07-25 12:31:37
0

在JavaScript中,我们可以用instanceof操作符来判断对象是否是某个类的实例,如果obj instaceof Class返回true,那么我们认为obj是Class的实例,obj要么由Class创建,要么由Class的子类创建。来自Java或其他强类型语言的开发者一定认为如果obj instaceof Class返回true,那么obj肯定拥有Class的所有属性。事实是这样么?我们看下面的代码:(斑头雁原创:http://bantouyan.iteye.com)

Js代码

  1. function ClassA()     
  2. {     
  3.     this.ma = 'ClassA';     
  4. }     
  5. ClassA.prototype.fa = function(){return 'prototype function';};     
  6.     
  7. function ClassB()     
  8. {     
  9.     this.mb = 'ClassB';     
  10. }     
  11. ClassB.prototype = ClassA.prototype;     
  12.     
  13. var obja = new ClassA();     
  14. alert(('ma' in obja) + ' ' + obja.hasOwnProperty('ma')); //output true true     
  15. alert(('mb' in obja) + ' ' + obja.hasOwnProperty('mb')); //output false false     
  16. alert(('fa' in obja) + ' ' + obja.hasOwnProperty('fa')); //output true false     
  17. alert(('fb' in obja) + ' ' + obja.hasOwnProperty('fb')); //output true false     
  18. alert(obja instanceof ClassA);   //output true     
  19. alert(obja instanceof ClassB);   //output true     
  20.     
  21. var objb = new ClassB();     
  22. alert(('ma' in objb) + ' ' + objb.hasOwnProperty('ma')); //output false false     
  23. alert(('mb' in objb) + ' ' + objb.hasOwnProperty('mb')); //output true true     
  24. alert(('fa' in objb) + ' ' + objb.hasOwnProperty('fa')); //output true false     
  25. alert(('fb' in objb) + ' ' + objb.hasOwnProperty('fb')); //output true false     
  26. alert(objb instanceof ClassA);   //output true     
  27. alert(objb instanceof ClassB);   //output true    

 

在这段代码中,我们定义了两个类,ClassA与ClassB,还给ClassA创建了原型方法fa,给ClassB创建了原型方法fb,并分别创建了对象obja与objb。直觉上,我们并不认为ClassA与ClassB是同一个类,所以obja不是ClassB的实例,objb也不是ClassA的实例,而且obja不会拥有属性fb,objb也不会拥有属性fa,但是运行结果告诉我们,JavaScript并不这样认为。obja与objb都拥有属性fa与fb,它们既是ClassA的实例也是ClassB的实例。下面我们分析一下原因。(斑头雁原创:http://bantouyan.iteye.com)

ClassA的prototype与ClassB的prototype是同一个对象,所以给ClassA增加原型方法fa会影响到ClassB,给ClassB增加的原型方法fb也会影响到ClassA,所以obja与objb都拥有属性fa与fb,这一点也比较容易理解。oba没有ClassB的实例属性mb但却是ClassB的实例,objb也没有ClassA的实例属性ma但却是ClassA的实例,这说明instanceof的判断与实例属性无关。既然instanceof与实例属性无关,那么它就跟原型属性有关。事实上,JavaScript根据原型判定instanceof的运算结果。(斑头雁原创:http://bantouyan.iteye.com)

我们知道同一个构造函数所创建的对象与这个构造函数共享同一个原型(只不一般不能直接访问过对象的原型),而ClassA与ClassB也共享同一个原型,那么obja与objb也共享同一个原型,所以可以这样认为,如果对象与类共享一个原型,那么对象就是这个类的实例,instanceof运算就返回true。下面我们看一下继承的情况。(斑头雁原创:http://bantouyan.iteye.com)

Js代码

  1. function ClassA()     
  2. {     
  3.     this.ma = 'ClassA';     
  4. }     
  5. ClassA.prototype.fa = function(){return 'prototype function fa';};     
  6.     
  7. function ClassB()     
  8. {     
  9.     this.mb = 'ClassB';     
  10. }     
  11. ClassB.prototype = ClassA.prototype;     
  12. ClassB.prototype.fb = function(){return 'prototype function fb';};     
  13.     
  14. function ClassC()     
  15. {     
  16.     this.mc = 'ClassC';     
  17. }     
  18. ClassC.prototype = new ClassB();     
  19. ClassC.prototype.fc = function(){return 'prototype function fc';};     
  20.     
  21. var objc = new ClassC();     
  22. alert(objc instanceof ClassB);   //output true     
  23. alert(objc instanceof ClassA);   //output true     
  24. alert(('ma' in objc) + ' ' + objc.hasOwnProperty('ma')); //output false false     
  25. alert(('mb' in objc) + ' ' + objc.hasOwnProperty('mb')); //output true false     
  26. alert(('mc' in objc) + ' ' + objc.hasOwnProperty('mc')); //output true true     
  27. alert(('fa' in objc) + ' ' + objc.hasOwnProperty('fa')); //output true false     
  28. alert(('fb' in objc) + ' ' + objc.hasOwnProperty('fb')); //output true false     
  29. alert(('fc' in objc) + ' ' + objc.hasOwnProperty('fc')); //output true false    

 

ClassC采用原型链方法继承了ClassB,所以ClassC的对象objc是ClassB的实例,但是运行结果告诉我们,objc也是ClassA的实例。objc是ClassC的实例,所以objc与ClassC共享一个原型。ClassC的原型是ClassB的实例,所以ClassC的原型的原型与ClassB的原型是同一个原型,而ClassB与ClassA共享同一个原型,所以ClassC的原型的原型与ClassA的原型是同一个原型,即objc的原型的原型与ClassA的原型是同一个原型。由此看来,instanceof可以根据对象原型的原型,即原型链上的原型,判定运算的结果,即如果类的原型与对象原型链上的某一个原型是同一个对象,那么instanceof运算将返回true,否则返回false。下面我们用一段更长的代码来验证这个结论。(斑头雁原创:http://bantouyan.iteye.com)

Js代码

  1. function ClassA()     
  2. {     
  3.     this.ma = 'ClassA';     
  4. }     
  5. ClassA.prototype.fa = function(){return 'prototype function fa';};     
  6.     
  7. function ClassB()     
  8. {     
  9.     this.mb = 'ClassB';     
  10. }     
  11. ClassB.prototype = ClassA.prototype;     
  12. ClassB.prototype.fb = function(){return 'prototype function fb';};     
  13.     
  14. function ClassC()     
  15. {     
  16.     this.mc = 'ClassC';     
  17. }     
  18. ClassC.prototype = new ClassB();     
  19. ClassC.prototype.fc = function(){return 'prototype function fc';};     
  20.     
  21. function ClassD()     
  22. {     
  23.     this.md = 'ClassD';     
  24. }     
  25. ClassD.prototype = ClassC.prototype;     
  26. ClassC.prototype.fd = function(){return 'prototype function fd';};     
  27.     
  28. function ClassE()     
  29. {     
  30.     this.me = 'ClassE';     
  31. }     
  32. ClassE.prototype = new ClassD();     
  33. ClassE.prototype.fe = function(){return 'prototype function fe';};     
  34.     
  35. var obje = new ClassE();     
  36. alert(obje instanceof ClassA);   //output true     
  37. alert(obje instanceof ClassB);   //output true     
  38. alert(obje instanceof ClassC);   //output true     
  39. alert(obje instanceof ClassD);   //output true     
  40. alert(obje instanceof ClassE);   //output true     
  41.     
  42. alert(('ma' in obje) + ' ' + obje.hasOwnProperty('ma')); //output false false     
  43. alert(('mb' in obje) + ' ' + obje.hasOwnProperty('mb')); //output true false     
  44. alert(('mc' in obje) + ' ' + obje.hasOwnProperty('mc')); //output false false     
  45. alert(('md' in obje) + ' ' + obje.hasOwnProperty('md')); //output true false     
  46. alert(('me' in obje) + ' ' + obje.hasOwnProperty('me')); //output true true     
  47.     
  48. alert(('fa' in obje) + ' ' + obje.hasOwnProperty('fa')); //output true false     
  49. alert(('fb' in obje) + ' ' + obje.hasOwnProperty('fb')); //output true false     
  50. alert(('fc' in obje) + ' ' + obje.hasOwnProperty('fc')); //output true false     
  51. alert(('fd' in obje) + ' ' + obje.hasOwnProperty('fd')); //output true false     
  52. alert(('fe' in obje) + ' ' + obje.hasOwnProperty('fe')); //output true false    

 

ClassA的原型与ClassB的原型共享同一个对象,ClassC的原型与ClassD的原型也共享一个对象,而ClassC是ClassB的子类,ClassE是ClassD的子类,而obje是ClassE的实例。所以obje的原型链的***个原型是ClassE的原型,它是ClassD的实例,故第二个原型是ClassD的原型,也就是ClassC的原型,ClassC的原型是ClassB的实例,所以原型链上第三个原型是ClassB的原型,也就是ClassA的原型。所以,ClassA、ClassB、ClassC、ClassD与ClassE的原型都在对象obje的原型链上,所以obje是这些类的实例。这也验证了前面的结论,即如果类的原型与对象原型链上的某一个原型是同一个对象,那么instanceof运算将返回true。虽然obje是ClassA、ClassC的实例,但是它并没有ClassA的实例属性ma,ClassC的实例属性mc。(斑头雁原创:http://bantouyan.iteye.com)

综合前面的论述与验证,我们可以得出结论,如果obj instanceof Class返回true,那么Class的原型与obj原型链上的某个原型是同一个对象,但这并不意味着obj拥有Class的所有实例属性(但肯定拥有Class的所有原型属性)。

【编辑推荐】

  1. 10个超棒的HTML 5素描及绘画设计工具
  2. 学习HTML 5十佳站点推荐
  3. 12个精妙有趣的HTML 5应用
  4. 10个令人惊奇的HTML5和JavaScript效果
  5. 技术大牛谈HTML 5设计原理

相关内容

热门资讯

如何允许远程连接到MySQL数... [[277004]]【51CTO.com快译】默认情况下,MySQL服务器仅侦听来自localhos...
如何利用交换机和端口设置来管理... 在网络管理中,总是有些人让管理员头疼。下面我们就将介绍一下一个网管员利用交换机以及端口设置等来进行D...
施耐德电气数据中心整体解决方案... 近日,全球能效管理专家施耐德电气正式启动大型体验活动“能效中国行——2012卡车巡展”,作为该活动的...
20个非常棒的扁平设计免费资源 Apple设备的平面图标PSD免费平板UI 平板UI套件24平图标Freen平板UI套件PSD径向平...
Windows恶意软件20年“... 在Windows的早期年代,病毒游走于系统之间,偶尔删除文件(但被删除的文件几乎都是可恢复的),并弹...
德国电信门户网站可实时显示全球... 德国电信周三推出一个门户网站,直观地实时提供其安装在全球各地的传感器网络检测到的网络攻击状况。该网站...
为啥国人偏爱 Mybatis,... 关于 SQL 和 ORM 的争论,永远都不会终止,我也一直在思考这个问题。昨天又跟群里的小伙伴进行...
《非诚勿扰》红人闫凤娇被曝厕所... 【51CTO.com 综合消息360安全专家提醒说,“闫凤娇”、“非诚勿扰”已经被黑客盯上成为了“木...