javascript之typeof、instanceof操作符使用探讨

  写javascirpt代码时,typeof和instanceof这两个操作符时不时就会用到,堪称必用。但是!使用它们总是不能直接的得到想要的结果,非常纠结,普遍的说法认为“这两个操作符或许是javascript中最大的设计缺陷,因为几乎不可能从他们那里得到想要的结果”

  typeof

  说明:typeof返回一个表达式的数据类型的字符串,返回结果为js基本的数据类型,包括number,boolean,string,object,undefined,function。

  从说明来看,貌似没什么问题。

  下面的代码写了一个数值变量,typeof后的结果是"number"。

  

复制代码 代码如下:

  var a = 1;

  console.log(typeof(a)); //=>number

  如果用Number类型的构造函数new一个变量的话,typeof后的结果是"object"。

  

复制代码 代码如下:

  var a = new Number(1);

  console.log(typeof(a)); //=>object

  上面的这两个输出结果看似没啥问题,这一点从书上看来是理所当然的事情,因为javascript就是这么设计的。

  但是!问题就在于既然调用了typeof就应该准确返回一个变量的类型,不管是直接用值创建的还是用类型的构造函数创建的,否则!我还用你做啥!

  那么对于:

  

复制代码 代码如下:

  var a = 1;

  var b = new Number(1);

  a和b变量的类型准确的说来都应该是Number才是想要的结果。

  而准确的类型信息保存在变量的内部属性 [[Class]] 的值中,通过使用定义在 Object.prototype 上的方法 toString来获取。

  获取类型信息:

  

复制代码 代码如下:

  var a = 1;

  var b = new Number(1);

  console.log(Object.prototype.toString.call(a));

  console.log(Object.prototype.toString.call(b));

  输出:

  

复制代码 代码如下:

  [object Number]

  [object Number]

  是不是已经很直接了,我们稍微处理一下,得到直接结果:

  

复制代码 代码如下:

  var a = 1;

  var b = new Number(1);

  console.log(Object.prototype.toString.call(a).slice(8,-1));

  console.log(Object.prototype.toString.call(b).slice(8,-1));

  输出:

  Number

  Number

  这就是想要的结果。

  为了更好的使用,我们封装一个方法,用来判断某个变量是否是某种类型:

  

复制代码 代码如下:

  function is(obj,type) {

  var clas = Object.prototype.toString.call(obj).slice(8, -1);

  return obj !== undefined && obj !== null && clas === type;

  }

  定义一些变量做过测试,先来看看它们的typeof输出:

  

复制代码 代码如下:

  var a1=1;

  var a2=Number(1);

  var b1="hello";

  var b2=new String("hello");

  var c1=[1,2,3];

  var c2=new Array(1,2,3);

  console.log("a1's typeof:"+typeof(a1));

  console.log("a2's typeof:"+typeof(a2));

  console.log("b1's typeof:"+typeof(b1));

  console.log("b2's typeof:"+typeof(b2));

  console.log("c1's typeof:"+typeof(c1));

  console.log("c2's typeof:"+typeof(c2));

  输出:

  a1's typeof:number

  a2's typeof:object

  b1's typeof:string

  b2's typeof:object

  c1's typeof:object

  c2's typeof:object

  我们再用新作的函数是一下:

  

复制代码 代码如下:

  console.log("a1 is Number:"+is(a1,"Number"));

  console.log("a2 is Number:"+is(a2,"Number"));

  console.log("b1 is String:"+is(b1,"String"));

  console.log("b2 is String:"+is(b2,"String"));

  console.log("c1 is Array:"+is(c1,"Array"));

  console.log("c2 is Array:"+is(c2,"Array"));

  输出:

  a1 is Number:true

  a2 is Number:true

  b1 is String:true

  b2 is String:true

  c1 is Array:true

  c2 is Array:true

  注:typeof也不是无用,实际用处是用来检测一个变量是否已经定义或者是否已经赋值。

  instanceof

  说明:判断一个对象是否为某一数据类型,或一个变量是否为一个对象的实例。

  instanceof 操作符用来比较两个内置类型的变量时一样力不从心,同样会对结果不满意。

  

复制代码 代码如下:

  console.log("abc" instanceof String); // false

  console.log("abc" instanceof Object); // false

  console.log(new String("abc") instanceof String); // true

  console.log(new String("abc") instanceof Object); // true

  只有在比较自定义的对象时才准确反映关系。

  

复制代码 代码如下:

  function Person() {}

  function Man() {}

  Man.prototype = new Person();

  console.log(new Man() instanceof Man); // true

  console.log(new Man() instanceof Person); // true