简单谈谈Javascript中类型的判断
数据类型的判断有这么几种方式
1、一元运算符typeOf
2、关系运算符instanceof
3、constructor属性
4、prototype属性
一、typeof
typeof的返回值有以下几种
简单粗暴的方法,直接看代码
//以下代码在版本GoogleChrome45.0.2454.101m中测试通过 //Numbers console.log(typeof37==='number'); console.log(typeof3.14==='number'); console.log(typeofMath.LN2==='number'); console.log(typeofInfinity==='number'); console.log(typeofNaN==='number');//尽管NaN是"Not-A-Number"的缩写,意思是"不是一个数字" console.log(typeofNumber(1)==='number');//不要这样使用! //Strings console.log(typeof""==='string'); console.log(typeof"bla"==='string'); console.log(typeof(typeof1)==='string');//console.log(typeof返回的肯定是一个字符串 console.log(typeofString("abc")==='string');//不要这样使用! //Booleans console.log(typeoftrue==='boolean'); console.log(typeoffalse==='boolean'); console.log(typeofBoolean(true)==='boolean');//不要这样使用! //Symbols console.log(typeofSymbol()==='symbol'); console.log(typeofSymbol('foo')==='symbol'); console.log(typeofSymbol.iterator==='symbol'); //Undefined console.log(typeofundefined==='undefined'); console.log(typeofblabla==='undefined');//一个未定义的变量,或者一个定义了却未赋初值的变量 //Objects使用Array.isArray或者Object.prototype.toString.call方法可以从基本的对象中区分出数组类型 console.log(typeof{a:1}==='object'); console.log(typeof[1,2,4]==='object'); console.log(typeof/^[a-zA-Z]{5,20}$/==='object'); console.log(typeof{name:'wenzi',age:25}==='object'); console.log(typeofnull==='object');//true //下面的容易令人迷惑,不要这样使用! console.log(typeofnewBoolean(true)==='object'); console.log(typeofnewNumber(1)==='object'); console.log(typeofnewDate()==='object'); console.log(typeofnewString("abc")==='object'); console.log(typeofnewError()==='object'); //函数 console.log(typeoffunction(){}==='function'); console.log(typeofMath.sin==='function');
typeof只能检查出来以上7几种类型
二、instanceof
instanceof运算符用于识别正在处理的对象的类型,要求开发者明确地确认对象为某特定类型
1、instanceof和constructor没有关系
varA=function(){}; A.prototype={}; varB={}; console.log(A.constructor);//functionFunction(){[nativecode]} console.log(B.constructor);//functionObject(){[nativecode]} vara=newA(); A.prototype={}; varb=newA(); b.constructor=A.constructor; console.log(a.constructor===A);//false console.log(a.constructor);//functionObject(){[nativecode]} console.log(typeofA);//functionObject(){[nativecode]} console.log(a.constructor===b.constructor);//false console.log(b.constructor);//functionFunction(){[nativecode]} console.log(ainstanceofA);//false console.log(binstanceofA);//true
2、instanceof又叫关系运算符,可以用来判断某个构造函数的prototype属性是否存在另外一个要检测对象的原型链上
varstr=newString("helloworld"); console.log(strinstanceofString);//true console.log(StringinstanceofFunction);//true console.log(strinstanceofFunction);//false
第三次输出为什么会返回false呢?原文地址:Javascript中一个关于instanceof的问题
//表达式一的指向 console.log(str.__proto__===String.prototype);//true console.log(strinstanceofString);//true //表达式二的指向 console.log(String.__proto__===Function.prototype);//true console.log(StringinstanceofFunction);//true //表达式三的指向 console.log(str.__proto__===String.prototype);//true console.log(str.__proto__.__proto__===String.prototype.__proto__);//true console.log(str.__proto__.__proto__===Object.prototype);//true console.log(str.__proto__.__proto__.__proto__===null);//true console.log(strinstanceofObject);//true console.log(strinstanceofFunction);//false
再看一个复杂的用法
console.log(ObjectinstanceofObject);//true console.log(FunctioninstanceofFunction);//true console.log(NumberinstanceofNumber);//false console.log(StringinstanceofString);//false console.log(FunctioninstanceofObject);//true console.log(FooinstanceofFunction);//true console.log(FooinstanceofFoo);//false
为什么,这是为什么呢,要搞明白以下含义
1、语言规范中是如何定义这个运算符的
2、JavaScript原型继承机制
ObjectinstanceofObject
//为了方便表述,首先区分左侧表达式和右侧表达式 ObjectL=Object,ObjectR=Object; console.log(ObjectLinstanceofObjectR);//true
//下面根据规范逐步推演 console.log(ObjectL.__proto__===Function.prototype);//true console.log(ObjectL.__proto__.__proto__===Object.prototype);//true
FunctioninstanceofFunction
FunctionL=Function,FunctionR=Function; console.log(FunctionLinstanceofFunctionR);//true console.log(FunctionL.__proto__===Function.prototype);//true FooinstanceofFoo functionFoo(){} varfoo=newFoo(); FooL=Foo,FooR=Foo; console.log(FooLinstanceofFooR);//false console.log(FooL.__proto__===Function.prototype);//true console.log(FooL.__proto__.__proto__===Object.prototype);//true console.log(FooL.__proto__.__proto__.__proto__===null);//true
instanceof在Dojo继承机制中的应用
在JavaScript中,是没有多重继承这个概念的,就像Java一样。但在Dojo中使用declare声明类时,是允许继承自多个类的
dojo.declare("Aoo",null,{}); dojo.declare("Boo",null,{}); dojo.declare("Foo",[Aoo,Boo],{}); varfoo=newFoo(); console.log(fooinstanceofAoo);//true console.log(fooinstanceofBoo);//false console.log(foo.isInstanceOf(Aoo));//true console.log(foo.isInstanceOf(Boo));//true
instanceof和多全局对象(多个frame或多个window之间的交互)
在浏览器中,我们的脚本可能需要在多个窗口之间进行交互。多个窗口意味着多个全局环境,不同的全局环境拥有不同的全局对象,从而拥有不同的内置类型构造函数。这可能会引发一些问题。比如,表达式[]instanceofwindow.frames[0].Array会返回false,因为Array.prototype!==window.frames[0].Array.prototype,因此你必须使用Array.isArray(myObj)或者Object.prototype.toString.call(myObj)==="[objectArray]"来判断myObj是否是数组。
//以下代码在版本GoogleChrome45.0.2454.101m中测试通过 //Numbers console.log(37instanceofNumber);//false console.log(3.14instanceofNumber);.//false console.log(Math.LN2instanceofNumber);//false console.log(InfinityinstanceofNumber);//false console.log(NaNinstanceofNumber);//false尽管NaN是"Not-A-Number"的缩写,意思是"不是一个数字" console.log(Number(1)instanceofNumber);//false不要这样使用! //Strings console.log(""instanceofString);//false console.log("bla"instanceofString);//false console.log((1)instanceofString);//falseconsole.log(返回的肯定是一个字符串 console.log(String("abc")instanceofString);//false不要这样使用! //Booleans console.log(trueinstanceofBoolean);//false console.log(falseinstanceofBoolean);//false console.log(Boolean(true)instanceofBoolean);//false不要这样使用! //Symbols console.log(Symbol()instanceofSymbol);//false console.log(Symbol("foo")instanceofSymbol);//false console.log(Symbol.iteratorinstanceofSymbol);//false //Undefined varblabla; //console.log(undefinedinstanceofUndefined);//UncaughtReferenceError:Undefinedisnotdefined //console.log(blablainstanceofUndefined);//UncaughtReferenceError:Undefinedisnotdefined console.log(undefinedinstanceofObject);//false console.log(blablainstanceofObject);//false //Objects使用Array.isArray或者Object.prototype.toString.call方法可以从基本的对象中区分出数组类型 console.log({a:1}instanceofObject);//true console.log([1,2,4]instanceofObject);//true console.log(/^[a-zA-Z]{5,20}$/instanceofObject);//true console.log({name:'wenzi',age:25}instanceofObject);//true console.log(null===Object);//false //下面的容易令人迷惑,不要这样使用! console.log(newBoolean(true)instanceofObject);//true console.log(newNumber(1)instanceofObject);//true console.log(newDate()instanceofObject);//true console.log(newString("abc")instanceofObject);//true console.log(newError()instanceofObject);//true //函数 console.log(function(){}instanceofFunction);//true console.log(Math.sininstanceofFunction);//true
注意:undefined和null是检测的Object类型,因为js中没有Undefined和Null的这种全局类型,number,string和boolean无法检测出它的类型
三、constructor
在使用instanceof检测变量类型时,我们是检测不到number,'string',bool的类型的。因此,我们需要换一种方式来解决这个问题
Object.prototype.constructor返回一个指向创建了该对象原型的函数引用。需要注意的是,该属性的值是那个函数本身,而不是一个包含函数名称的字符串。对于原始值(如1,true或"test"),该属性为只读,所有对象都会从它的原型上继承一个constructor属性
constructor本来是原型对象上的属性,指向构造函数。但是根据实例对象寻找属性的顺序,若实例对象上没有实例属性或方法时,就去原型链上寻找,因此,实例对象也是能使用constructor属性的
functionPerson(){ } varTom=newPerson(); console.log(Tom.constructor===Person);//true
不过要注意,constructor属性是可以被修改的,会导致检测出的结果不正确
functionPerson(){ } functionStudent(){ } Student.prototype=newPerson(); varJohn=newStudent(); console.log(John.constructor==Student);//false console.log(John.constructor==Person);//true
改变这个对象的constructor属性的值
functionType(){}; vartypes=[ newArray, [], newBoolean, true,//remainsunchanged newDate, newError, newFunction, function(){}, Math, newNumber, 1,//remainsunchanged newObject, {}, newRegExp, /(?:)/, newString, "test"//remainsunchanged ]; for(vari=0;i<types.length;i++){ types[i].constructor=Type; types[i]=[types[i].constructor,types[i]instanceofType,types[i].toString()]; }; console.log(types.join("\n"));
除了undefined和null,其他类型的变量均能使用constructor判断出类型
四、万能的Object.prototype.toString.call
使用toString()方法来检测对象类型
functionType(){}; vartoString=Object.prototype.toString; console.log(toString.call(newDate)==='[objectDate]');//true console.log(toString.call(newString)==='[objectString]');//true console.log(toString.call(newFunction)==='[objectFunction]');//true console.log(toString.call(Type)==='[objectFunction]');//true console.log(toString.call('str')==='[objectString]');//true console.log(toString.call(Math)==='[objectMath]');//true console.log(toString.call(true)==='[objectBoolean]');//true console.log(toString.call(/^[a-zA-Z]{5,20}$/)==='[objectRegExp]');//true console.log(toString.call({name:'wenzi',age:25})==='[objectObject]');//true console.log(toString.call([1,2,3,4])==='[objectArray]');//true //SinceJavaScript1.8.5 console.log(toString.call(undefined)==='[objectUndefined]');//true console.log(toString.call(null)==='[objectNull]');//true
附上判断函数Javascript中的数据类型知多少
五、jquery的实现 jquery:"1.8.2",
jquery中提供了一个$.type的接口,看看代码
varm=Object.prototype.toString//501行 E={};//512行 isFunction:function(a){//645行 returnp.type(a)==="function" }, isArray:Array.isArray||function(a){ returnp.type(a)==="array" } , isWindow:function(a){ returna!=null&&a==a.window }, isNumeric:function(a){ return!isNaN(parseFloat(a))&&isFinite(a) }, type:function(a){ returna==null?String(a):E[m.call(a)]||"object" }, isPlainObject:function(a){ if(!a||p.type(a)!=="object"||a.nodeType||p.isWindow(a)) return!1; try{ if(a.constructor&&!n.call(a,"constructor")&&!n.call(a.constructor.prototype,"isPrototypeOf")) return!1 }catch(c){ return!1 } vard; for(dina) ; returnd===b||n.call(a,d) }, isEmptyObject:function(a){ varb; for(bina) return!1; return!0 },
可以看出来,jquery中就是用Object.prototype.toString.call实现的