详解JavaScript中typeof与instanceof用法
今天写JS代码,遇到动态生成多个名称相同的input复选按钮
需要判断其是否是数组,用到了if(typeof(document.MapCheckMgr.checkid)!="undefined")
以前用得少,就顺便查了一下关于typeof的那些事
typeof用以获取一个变量或者表达式的类型,typeof一般只能返回如下几个结果:
number,boolean,string,function(函数),object(NULL,数组,对象),undefined。
如:
alert(typeof(123));//typeof(123)返回"number" alert(typeof("123"));//typeof("123")返回"string"
我们可以使用typeof来获取一个变量是否存在,如if(typeofa!="undefined"){},而不要去使用if(a)因为如果a不存在(未声明)则会出错,
正因为typeof遇到null,数组,对象时都会返回object类型,所以当我们要判断一个对象是否是数组时
或者判断某个变量是否是某个对象的实例则要选择使用另一个关键语法instanceof
instanceof用于判断一个变量是否某个对象的实例,如vara=newArray();alert(ainstanceofArray);会返回true,
同时alert(ainstanceofObject)也会返回true;这是因为Array是object的子类。
再如:functiontest(){};vara=newtest();alert(ainstanceoftest)会返回true。
关于typeof
typeof一元运算符,用来返回操作数类型的字符串。
typeof几乎不可能得到它们想要的结果。typeof只有一个实际应用场景,就是用来检测一个对象是否已经定义或者是否已经赋值。而这个应用却不是来检查对象的类型。
Value | Class | Type |
---|---|---|
"foo" | String | string |
newString("foo") | String | object |
1.2 | Number | number |
newNumber(1.2) | Number | object |
true | Boolean | boolean |
newBoolean(true) | Boolean | object |
newDate() | Date | object |
newError() | Error | object |
[1,2,3] | Array | object |
newArray(1,2,3) | Array | object |
newFunction("") | Function | function |
/abc/g | RegExp | object(functioninNitro/V8) |
newRegExp("meow") | RegExp | object(functioninNitro/V8) |
{} | Object | object |
newObject() | Object | object |
上面表格中,Type一列表示typeof操作符的运算结果。可以看到,这个值在大多数情况下都返回"object"。
Class一列表示对象的内部属性[[Class]]的值。
JavaScript标准文档中定义:[[Class]]的值只可能是下面字符串中的一个:Arguments,Array,Boolean,Date,Error,Function,JSON,Math,Number,Object,RegExp,String.
为了获取对象的[[Class]],我们需要使用定义在Object.prototype上的方法toString。
对象的类定义
JavaScript标准文档只给出了一种获取[[Class]]值的方法,那就是使用Object.prototype.toString。
functionis(type,obj){ varclas=Object.prototype.toString.call(obj).slice(8,-1); returnobj!==undefined&&obj!==null&&clas===type; } is('String','test');//true is('String',newString('test'));//true
上面例子中,Object.prototype.toString方法被调用,this被设置为了需要获取[[Class]]值的对象。
注:Object.prototype.toString返回一种标准格式字符串,所以上例可以通过slice截取指定位置的字符串,如下所示:
Object.prototype.toString.call([])//"[objectArray]" Object.prototype.toString.call({})//"[objectObject]" Object.prototype.toString.call(2)//"[objectNumber]"
注:这种变化可以从IE8和Firefox4中看出区别,如下所示:
//IE8 Object.prototype.toString.call(null)//"[objectObject]" Object.prototype.toString.call(undefined)//"[objectObject]" //Firefox4 Object.prototype.toString.call(null)//"[objectNull]" Object.prototype.toString.call(undefined)//"[objectUndefined]"
测试为定义变量
typeoffoo!=='undefined'
上面代码会检测foo是否已经定义;如果没有定义而直接使用会导致ReferenceError的异常。这是typeof唯一有用的地方。
结论
为了检测一个对象的类型,强烈推荐使用Object.prototype.toString方法;因为这是唯一一个可依赖的方式。正如上面表格所示,typeof的一些返回值在标准文档中并未定义,因此不同的引擎实现可能不同。
除非为了检测一个变量是否已经定义,我们应尽量避免使用typeof操作符。
x | typeofx |
---|---|
undefined | "undefined" |
true或false | "boolean" |
任意数字或者NaN | "number" |
任意字符串 | "string" |
函数对象(在ECMA-262术语中,指的是实现了[[Call]]的对象) | "function" |
任意内置对象(非函数) | "object" |
数组 | "obeject" |
null | "object" |
宿主对象(JS引擎内置对象,而不是DOM或者其他提供的) | 由编译器各自实现的字符串,但不是"undefined","number","boolean","number","string"。 |
正则表达式 | 各浏览器表现不一 |
如果想将null和对象区分开,则必须针对特殊值显式检测。如:my_value===null。对于宿主对象来说,typeof有可能并不返回‘object',而返回字符串。但实际上客户端js中的大多数宿主对象都是‘object'类型。对于所有内置可执行对象进行typeof运算都将返回“function”。
//Numbers typeof37==='number'; typeof3.14==='number'; typeofMath.LN2==='number'; typeofInfinity==='number'; typeofNaN==='number';//尽管NaN是"Not-A-Number"的缩写,意思是"不是一个数字" typeofNumber(1)==='number';//不要这样使用! //Strings typeof""==='string'; typeof"bla"==='string'; typeof(typeof1)==='string';//typeof返回的肯定是一个字符串 typeofString("abc")==='string';//不要这样使用! //Booleans typeoftrue==='boolean'; typeoffalse==='boolean'; typeofBoolean(true)==='boolean';//不要这样使用! //Undefined typeofundefined==='undefined'; typeofblabla==='undefined';//一个未定义的变量,或者一个定义了却未赋初值的变量 //Objects typeof{a:1}==='object'; typeof[1,2,4]==='object'; //使用Array.isArray或者Object.prototype.toString.call方法 //可以分辨出一个数组和真实的对象 typeofnewDate()==='object'; typeofnewBoolean(true)==='object'//令人困惑.不要这样使用 typeofnewNumber(1)==='object'//令人困惑.不要这样使用 typeofnewString("abc")==='object';//令人困惑.不要这样使用 //Functions typeoffunction(){}==='function'; typeofMath.sin==='function';
关于instanceof
instanceof左操作数是一个类,右操作数是标识对象的类。如果左侧的对象是右侧类的实例,则返回true.而js中对象的类是通过初始化它们的构造函数来定义的。即instanceof的右操作数应当是一个函数。所有的对象都是object的实例。如果左操作数不是对象,则返回false,如果右操作数不是函数,则抛出typeError。
instanceof运算符是用来测试一个对象是否在其原型链原型构造函数的属性。其语法是objectinstanceofconstructor
instanceof操作符用来比较两个操作数的构造函数。只有在比较自定义的对象时才有意义。如果用来比较内置类型,将会和typeof操作符一样用处不大。
比较自定义对象
functionFoo(){} functionBar(){} Bar.prototype=newFoo(); newBar()instanceofBar;//true newBar()instanceofFoo;//true //如果仅仅设置Bar.prototype为函数Foo本身,而不是Foo构造函数的一个实例 Bar.prototype=Foo; newBar()instanceofFoo;//false
instanceof比较内置类型
newString('foo')instanceofString;//true newString('foo')instanceofObject;//true 'foo'instanceofString;//false 'foo'instanceofObject;//false
有一点需要注意,instanceof用来比较属于不同JavaScript上下文的对象(比如,浏览器中不同的文档结构)时将会出错,因为它们的构造函数不会是同一个对象。
结论:instanceof操作符应该仅仅用来比较来自同一个JavaScript上下文的自定义对象。正如typeof操作符一样,任何其它的用法都应该是避免的。
functionC(){}//definingaconstructor functionD(){}//defininganotherconstructor varo=newC(); oinstanceofC;//true,because:Object.getPrototypeOf(o)===C.prototype oinstanceofD;//false,becauseD.prototypeisnowhereino'sprototypechain oinstanceofObject;//true,because: C.prototypeinstanceofObject//true C.prototype={}; varo2=newC(); o2instanceofC;//true oinstanceofC;//false,becauseC.prototypeisnowhereino'sprototypechainanymore D.prototype=newC();//useinheritance varo3=newD(); o3instanceofD;//true o3instanceofC;//true varmyString=newString(); varmyDate=newDate(); myStringinstanceofString;//returnstrue myStringinstanceofObject;//returnstrue myStringinstanceofDate;//returnsfalse myDateinstanceofDate;//returnstrue myDateinstanceofObject;//returnstrue myDateinstanceofString;//returnsfalse functionCar(make,model,year){ this.make=make; this.model=model; this.year=year; } varmycar=newCar("Honda","Accord",1998); vara=mycarinstanceofCar;//returnstrue varb=mycarinstanceofObject;//returnstrue
总结
以上所述是小编给大家介绍的JavaScript中typeof与instanceof用法,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对毛票票网站的支持!