简单谈谈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实现的