instanceof和typeof运算符都能用来判断一个变量是否为空或是什么类型。typeof用以获取一个变量的类型,typeof一般只能返回如下几个结果果:number, boolean, string, function, object, undefined。我们可以使用typeof来获取一个变量是否存在,如if(typeof a!=“undefined”){//TODO},对于Date, Array, Null等特殊对象使用typeof一律返回object,这正是typeof的局限性。instanceof用于判断一个变量是否某个对象的实例,如var a=new Array(); alert(a instanceof Array);会返回true,同时alert(a instanceof Object)也会返回true;这是因为Array是object的子类。
1、typeof运算符
typeof是一元运算符,放在操作数前面,返回表示操作数类型的一个字符串。任意操作数在typeof运算后返回值如下:
操作数 x | typeof x | example |
---|---|---|
undefined | “undefined” | var a; typeof a; //undefiend |
null | “object” | var a = null; typeof a; //object |
true | “boolean” | var a = true; typeof a; //boolean |
数字或NaN | “number” | var a = “12” - 0; typeof a; //number |
任意字符串 | “string” | var a = 12 + “”; typeof a; //string |
任意函数 | “function” | var a = function(){}; function b(){}; typeof a; typeof b;//function function |
任意内置对象 | “object” | var a = new Date, b = new Array(1); typeof a; type b; //object object |
通过上表我们可以看出typeof返回4类值:
- 原始值:string, number, boolean
- undefined
- function
- object:Date, Array等
注意function其实是object的一种,但是typeof返回function而不是object,需要注意,原因可以简单理解为:function是可执行的,根据ECMAScript3规范,对于所有内置可执行对象,typeof运算符一律返回"function"。
typeof运算对于判断操作数是原始值类型还是对象类型,尤其判断变量是否定义过非常有用,但是对于判断具体是Date还是Array还是其它就无能为力啦,需要instanceof运算符或其它技术手段实现。
2、instanceof运算符
instanceof运算符希望左操作数是一个对象,右操作数标识对象类型的类。如果左侧对象是右侧类的实例,则返回true,否则返回false。通俗点理解就是:instanceof判断一个对象是否为某一数据类型,或一个变量是否为一个对象的实例。看个案例:
var d = new Date;
d instanceof Date; //true
d instanceof Object; //true, 所有对象都是object的实例
d instanceof Number; //false
var a = [1,2,3];
a instanceof Array; //true
a instanceof Object; //true, 所有数组都是对象
a instanceof RegExp; //false
instanceof工作机制基于JavaScript原型链,类似Java继承关系。为了计算表达式o instanceof f,首先计算f.prototype,然后在o的原型链中查找f.prototype,如果找到,那么o是f的一个实例,表达式返回true。如果f.prototype不在o的原型链中,那么o就不是f的一个实例,表达式返回false。
判断:o.proto.proto…会不会等于f.prototype, 看个案例:
function C(){}
function D(){}
var o = new C();
console.log('o instanceof C: ', o instanceof C); // true, o.__proto__ == C.prototype
console.log('o instanceof D: ', o instanceof D); // false, D.prototype不在o的原型链上
console.log('o instanceof Object: ', o instanceof Object); // true, o.__proto__.__proto__ == Object.prototype
console.log(C.prototype instanceof Object) // true, C.prototype.__proto__ = Object.prototype
C.prototype = {};
var o2 = new C();
console.log(o2 instanceof C); // true
console.log("o instanceof C", o instanceof C); //false, C.prototype指向了一个空对象,这个对象不在o的原型链上.
D.prototype = new C();
var o3 = new D();
o3 instanceof D; // true,
o3 instanceof C; // true, o3是D的实例,而D继承C
关于JavaScript原型、原型链、Constuctor等大家可以参考:
1)JS原型链简单图解
2)深入理解JavaScript系列(5):强大的原型和原型链
3)Js中Prototype、proto、Constructor、Object、Function关系介绍
3、类型判断TypeUtil的简单实现
我们可以通过Object.prototype.toString方法,判断某个对象值属于哪种内置类型,一个案例:
var TypeUtil = (function() {
return {
isString: function(str) {
return Object.prototype.toString.call(str) === "[object String]";
},
isNumber: function(num) {
return Object.prototype.toString.call(num) === "[object Number]";
},
isBoolean: function(flag) {
return Object.prototype.toString.call(flag) === "[object Boolean]";
},
isFunc: function(fn) {
return Object.prototype.toString.call(fn) === "[object Function]";
},
isArray: function(arr) {
return Object.prototype.toString.call(arr) === "[object Array]";
},
isObject: function(obj) {
return Object.prototype.toString.call(obj) === "[object Object]";
}
};
}());
console.log("TypeUtil.isString: ", TypeUtil.isString("1212")); //true
console.log("TypeUtil.isNumber: ", TypeUtil.isNumber(1212)); //true
console.log("TypeUtil.isBoolean: ", TypeUtil.isBoolean(true)); //true