JavaScript操作符instanceof揭秘

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

function ClassA()
{
    this.ma = 'ClassA';
}
ClassA.prototype.fa = function(){return 'prototype function';};

function ClassB()
{
    this.mb = 'ClassB';
}
ClassB.prototype = ClassA.prototype;

var obja = new ClassA();
alert(('ma' in obja) + ' ' + obja.hasOwnProperty('ma')); //output true true
alert(('mb' in obja) + ' ' + obja.hasOwnProperty('mb')); //output false false
alert(('fa' in obja) + ' ' + obja.hasOwnProperty('fa')); //output true false
alert(('fb' in obja) + ' ' + obja.hasOwnProperty('fb')); //output true false
alert(obja instanceof ClassA);   //output true
alert(obja instanceof ClassB);   //output true

var objb = new ClassB();
alert(('ma' in objb) + ' ' + objb.hasOwnProperty('ma')); //output false false
alert(('mb' in objb) + ' ' + objb.hasOwnProperty('mb')); //output true true
alert(('fa' in objb) + ' ' + objb.hasOwnProperty('fa')); //output true false
alert(('fb' in objb) + ' ' + objb.hasOwnProperty('fb')); //output true false
alert(objb instanceof ClassA);   //output true
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)

function ClassA()
{
    this.ma = 'ClassA';
}
ClassA.prototype.fa = function(){return 'prototype function fa';};

function ClassB()
{
    this.mb = 'ClassB';
}
ClassB.prototype = ClassA.prototype;
ClassB.prototype.fb = function(){return 'prototype function fb';};

function ClassC()
{
    this.mc = 'ClassC';
}
ClassC.prototype = new ClassB();
ClassC.prototype.fc = function(){return 'prototype function fc';};

var objc = new ClassC();
alert(objc instanceof ClassB);   //output true
alert(objc instanceof ClassA);   //output true
alert(('ma' in objc) + ' ' + objc.hasOwnProperty('ma')); //output false false
alert(('mb' in objc) + ' ' + objc.hasOwnProperty('mb')); //output true false
alert(('mc' in objc) + ' ' + objc.hasOwnProperty('mc')); //output true true
alert(('fa' in objc) + ' ' + objc.hasOwnProperty('fa')); //output true false
alert(('fb' in objc) + ' ' + objc.hasOwnProperty('fb')); //output true false
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)

function ClassA()
{
    this.ma = 'ClassA';
}
ClassA.prototype.fa = function(){return 'prototype function fa';};

function ClassB()
{
    this.mb = 'ClassB';
}
ClassB.prototype = ClassA.prototype;
ClassB.prototype.fb = function(){return 'prototype function fb';};

function ClassC()
{
    this.mc = 'ClassC';
}
ClassC.prototype = new ClassB();
ClassC.prototype.fc = function(){return 'prototype function fc';};

function ClassD()
{
    this.md = 'ClassD';
}
ClassD.prototype = ClassC.prototype;
ClassC.prototype.fd = function(){return 'prototype function fd';};

function ClassE()
{
    this.me = 'ClassE';
}
ClassE.prototype = new ClassD();
ClassE.prototype.fe = function(){return 'prototype function fe';};

var obje = new ClassE();
alert(obje instanceof ClassA);   //output true
alert(obje instanceof ClassB);   //output true
alert(obje instanceof ClassC);   //output true
alert(obje instanceof ClassD);   //output true
alert(obje instanceof ClassE);   //output true

alert(('ma' in obje) + ' ' + obje.hasOwnProperty('ma')); //output false false
alert(('mb' in obje) + ' ' + obje.hasOwnProperty('mb')); //output true false
alert(('mc' in obje) + ' ' + obje.hasOwnProperty('mc')); //output false false
alert(('md' in obje) + ' ' + obje.hasOwnProperty('md')); //output true false
alert(('me' in obje) + ' ' + obje.hasOwnProperty('me')); //output true true

alert(('fa' in obje) + ' ' + obje.hasOwnProperty('fa')); //output true false
alert(('fb' in obje) + ' ' + obje.hasOwnProperty('fb')); //output true false
alert(('fc' in obje) + ' ' + obje.hasOwnProperty('fc')); //output true false
alert(('fd' in obje) + ' ' + obje.hasOwnProperty('fd')); //output true false
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的所有原型属性)。(斑头雁原创:http://bantouyan.iteye.com)

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
该资源内项目源码是个人的课程设计、毕业设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。 该资源内项目源码是个人的课程设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值