对JavaScript instanceof运算符的深入分析
运算符实例介绍
在JavaScript中,typeof运算符用于判断变量的类型。使用Typeof运算符时,按引用类型存储值存在问题。无论引用什么类型的对象,它都会返回“object”。ECMAScript引入了另一个Java操作符instanceof来解决这个问题。instanceof运算符类似于typeof运算符,用于标识正在处理的对象的类型。与typeof方法不同,instanceof方法要求开发人员明确确认对象属于特定类型。例如:
清单1。示例
var ostringObject=new String(' hello world ');console . log(ostringobjectinstance of String);//输出‘true’这段代码询问“变量oStringObject是String对象的实例吗?”OStringObject确实是String对象的一个实例,所以结果是“真”。虽然不如typeof方法灵活,但当typeof方法返回“object”时,instanceof方法很有用。
运算符instanceof的一般用法
一般来说,使用instanceof是判断一个实例是否属于某个类型。例如:
清单2。一般用法举例
//判断foo是否是Foo类函数Foo(){ } var Foo=new Foo();console . log(foo instanceof foo)//true另外,更重要的一点是instance of可以用来判断一个实例在继承关系中是否属于其父类型。例如:
清单3。instanceof在继承关系中的使用
//判断foo是否是Foo类的实例及其父类型function aoo(){ } function Foo(){ } Foo . prototype=new oo();//JavaScript原型继承var Foo=new Foo();console . log(foo instanceof foo)//true console . log(aoo的foo instance)//true上面的代码确定了一级继承关系中的父类,instance of运算符也适用于多级继承关系。
你真的知道运算符的实例吗?
看完上面的代码示例,你觉得instanceof运算符很简单吗?让我们看看复杂的用法。
清单4。复杂用法的实例
控制台日志(对象的对象实例);//true console.log(函数的函数实例);//真正的控制台.日志(数字的数字实例);//false console.log(String的字符串实例);//false console.log(对象的函数实例);//true console . log(Foo instance of Function);//true console . log(Foo instance of Foo);//false看完上面的代码你是不是很迷茫?为什么对象和函数实例本身等于真,而其他类实例本身不等于真?怎么解释?要从根本上理解实例的奥秘,需要从两个方面入手:1。如何在语言规范中定义这个运算符?2.JavaScript原型的继承机制。
ECMAScript-262第3版中instanceof运算符定义的详细分析
语言规范如下定义了中的instanceof运算符:
清单5。规范中运算符定义的实例
11.8.6运算符生产关系表达式:关系表达式的实例计算如下3360 1。计算关系表达式。2 .调用GetValue (Result(1))。//调用getvalue方法获取结果(1)的值。设为结果(2) 3。计算shift表达式。4.调用getvalue(结果(3))。//类似地,设置为结果(4) 5。如果结果(4)不是这里的对象。引发类型错误异常。//如果结果(4)不是对象,//抛出异常。/*如果结果(4)没有[[HasInstance]]方法,抛出异常。全部[.]]规范中的方法或属性是内部的,不能直接在JavaScript中使用。并且规范指出只有Function对象实现[[HasInstance]]方法。所以可以简单理解为:如果Result(4)不是Function对象,抛出异常*/6。如果结果(4)没有[[有实例]]方法,抛出typeerrorexception。//相当于调用:result (4)。[[hasinstance]](结果(2)) 7。使用参数result (2)调用结果(4)的[[hasinstance]]方法。8 .返回结果(7)。//相关的HasInstance方法定义了15.3.5.3[[HasInstance]](v)假设f是一个函数对象。//其中f为上述结果(4)。v是结果(2)当用值v调用f的[[has instance]]方法时,将执行以下步骤3360 1。如果v不是对象,返回false。//如果v不是对象,直接返回false 2。调用属性名为“prototype”的f的[[Get]]方法。//使用[[get]]方法获取//F 3的原型属性。设o为结果(2)。//o=f .[[get]](“prototype”)4。如果O不是一个对象,抛出一个typeerror异常。5.设v为v .//v=v .[[原型]] 6的[[原型]]属性的值。如果v为空,则返回false。//这是关键,如果O和V指的是同一个对象,返回true;否则,转到步骤8,返回步骤5并继续循环7。如果o和v指的是同一个物体,或者它们指的是相互连接的物体(第13.1.2节)。回归真实。8.转到第5步。上面的规范定义晦涩复杂,涉及许多概念,但是将这个规范翻译成JavaScript代码非常简单,如下所示:
清单6。运算符代码的JavaScript实例
函数实例_的(L,R) {//L表示左表达式,R表示右表达式var O=R . prototype://取r l=l. _ _ prototype _ _//取l while的隐式原型(true) {if (l===null)返回falseIf (O===L)//这里的重点是:当O严格等于L时,返回真返回真;L=L. _ _ proto _ _} }JavaScript原型继承机制
由于本文主要分析JavaScript instanceof operator,因此我们将不详细解释JavaScript的原型继承机制。这里,我们参考一张来自http://www.mollypages.org/misc/js.mp,的图片,它详细描述了JavaScript中各种对象的显示和隐式原型链结构。
由于本文涉及显式原型和隐式原型,下面简单解释两个概念。在JavaScript原型的继承结构中,规范中使用[[Prototype]]表示对象的隐式原型,JavaScript中使用_ _ prototype _ _这个属性,在Firefox和Chrome浏览器中可以访问,但在IE中不能。
所有的JavaScript对象都有__proto__属性,但只有Object.prototype.__proto__为空,前提是该属性没有在Firefox或Chrome下修改。这个属性指向它的原型对象。至于显示的原型,在JavaScript中用prototype属性表示,这是JavaScript原型继承的基础知识,这里不再赘述。
JavaScript原型链
解释instanceof的复杂用法
有了上面instanceof运算符的JavaScript代码和原型继承图,就很容易理解instanceof运算符了。下面将详细说明Object的Object instanceof、Function的Function instanceof和Foo的Foo instanceof三个例子,其他例子的读者可以自行推导。
清单7。对象的对象实例
//为了表示方便,先区分左表达式和右表达式ObjectL=Object,ObjectR=Object//根据规范,o=objectr . prototype=object . prototype l=object l。_ _ proto _ _=function.prototype//judge o第一次!=L //循环查找L是否还有_ _ proto _ _ l=函数。原型。_ _ proto _ _=对象。原型//第二判断O==L //返回真清单8。函数的函数实例
//为了便于呈现,先区分左表达式和右表达式函数l=function,函数r=function//根据规范,o=function r . prototype=function . prototype l=function l . _ _ proto _ _=function.prototype//judge第一次o==l//返回true清单9。Foo实例
//为了表示方便,先区分左表达式和右表达式的FoU=Foo,FooR=Foo//根据规范,o=foor。原型=foo。原型l=foo。_ _ proto _ _=函数。原型//第一次判断o!=L //循环查找L是否还有_ _ proto _ _ l=函数。原型。_ _ proto _ _=对象。原型//第二次判断o!=L //找出L是否还有_ _ proto _ _ l=对象。原型。_ _ proto _ _=再次为null//判断l==第三次为null//返回false。分析instanceof在Dojo继承机制中的应用
在JavaScript中,没有多重继承的概念,就像Java一样。但是,在Dojo中声明一个类时,允许从多个类继承。下面以Dojo 1.6.1为例。
清单10。Dojo中的多重继承
dojo.declare('Aoo ',null,{ });dojo.declare('Boo ',null,{ });dojo.declare('Foo ',[Aoo,Boo],{ });var Foo=new Foo();console . log(foo instance of Aoo);//true console . log(foo instance of Boo);//false console . log(foo . Isinstanceof(Aoo));//true console . log(foo . Isinstanceof(Boo));//true在上面的示例中,foo同时继承了Aoo和Boo,但是当使用instanceof运算符检查Foo是否是Boo的实例时,它返回false。其实在Dojo中,Foo还是只继承自Aoo,Boo类中的方法和属性是通过mixin机制复制到Foo的,所以在使用instanceof运算符检查是否是Boo的实例时,会返回false。因此,Dojo为每个类实例添加了一个名为isInstanceOf的新方法,用于检查多重继承。
结束语
本文详细介绍了JavaScript语言中的instanceof运算符,并结合语言规范对该运算符的算法进行了深入分析。用JavaScript编写复杂的面向对象程序对读者会有帮助。本文的所有代码都通过了火狐15下的测试。
以上就是本文的全部内容。希望对大家的学习有帮助,支持我们。
版权声明:对JavaScript instanceof运算符的深入分析是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。