在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)
分享到:
相关推荐
实际上,在一个Web应用程序的执行期间,PHP 5提供给开发者至少两种方法来检查对象类型——它们分别是“instanceof”操作符和“类型提示”特征。本文将介绍PHP 5中\"instanceof\"操作符的使用;你很快就会发现,它...
当调用`new`操作符创建一个新实例时,这个实例的`__proto__`就被设置为构造函数的`prototype`。 下面是一个手动实现`instanceof`的例子: ```javascript function myInstanceof(obj, constructor) { let ...
`instanceof`是JavaScript中的一个操作符,用于检查一个对象是否是特定构造函数的实例,或者更具体地说,是检查该对象的原型链上是否存在指定构造函数的`prototype`。这个操作符对于理解和处理对象继承关系非常关键...
- **类型操作符**: 包括 `typeof`, `instanceof` 等。 每种操作符都有其特定的应用场景和用途,在编写代码时选择合适的操作符可以使程序更加高效、易读。例如,使用 `&&` 和 `||` 可以简化条件判断语句,使用 `...
写javascirpt代码时,typeof和instanceof这两个操作符时不时就会用到,堪称必用。但是!使用它们总是不能直接的得到想要的结果,非常纠结,普遍的说法认为“这两个操作符或许是javascript中最大的设计缺陷,因为几乎...
在JavaScript中,`instanceof`操作符用于检测一个对象是否属于某个类的实例。这个操作符在日常开发中被广泛使用,但有时它可能会表现出一些意外的行为,这可能被误认为是“bug”。本文将深入探讨`instanceof`的工作...
在JavaScript中,`new`操作符是一个至关重要的概念,它用于通过构造函数创建新的对象实例。构造函数是一种特殊类型的函数,通常用来初始化新创建的对象。接下来我们将深入探讨`new`操作符的工作原理,并通过示例进行...
instanceof是JavaScript中的一个操作符,它用于检测构造函数的prototype属性是否出现在某个实例对象的原型链上。也就是说,instanceof用于判断一个变量是否某个构造函数创建的对象的实例。 例如: ```javascript ...
在 JavaScript 中,instanceof 和 typeof 是两个常用的操作符,用于判断变量的类型和实例关系。然而,许多开发者对这两个操作符的区别和使用场景不够清楚,导致在编程中出现错误。下面,我们将详细介绍 instanceof ...
在JavaScript中,`typeof`和`instanceof`是两种常用的类型检查操作符,它们都用于检测变量的类型,但有着不同的用法和返回结果。理解它们的区别对于编写健壮的JavaScript代码至关重要。 `typeof`是一个一元操作符,...
NULL 博文链接:https://xiaoyu1985ban.iteye.com/blog/940991
JavaScript中的instanceof运算符是面向对象编程中非常重要的一个概念,它用于检测一个实例对象的原型链上是否包含某个构造函数的原型。instanceof运算符的使用有助于理解JavaScript中的原型继承机制。 在JavaScript...
总之,typeof和instanceof是JavaScript中判断变量类型的两个重要操作符。它们各有优势和局限,理解并合理运用它们能帮助开发者编写更加健壮和准确的代码。在进行类型检查时,要根据实际情况灵活选择合适的方法,并...
首先,我们来理解`instanceof`操作符。`instanceof`用于判断一个对象是否属于某个构造函数的实例。它的工作原理是检查对象的原型链中是否存在指定构造函数的`prototype`属性。如果存在,那么返回`true`,否则返回`...
在Java编程语言中,`instanceof`操作符是一个至关重要的工具,它允许程序员在运行时检查对象的类型。`instanceof`主要用于确定一个对象是否属于某个特定类、接口或者其子类(或实现)。理解`instanceof`的使用和原理...
特别是对于JavaScript中的instanceof操作符的深入理解,是前端开发者应该掌握的一个重要知识点。instanceof操作符常用于判断一个实例对象是否为某个类的实例,或者实例是否属于某个类的原型链上。 ### instanceof...
3. instanceof操作符:这个操作符用于检查一个实例是否属于某个构造函数的原型链中。换言之,instanceof用于判断一个实例对象a是否属于某个构造函数A的实例。如果实例a的原型链上能找到构造函数A.prototype,则返回...