js:typeof与instanceof区别

typeof


 

typeof运算符返回一个用来表示表达式的数据类型的字符串。

返回值为6个字符串,分别为stringBooleannumberfunctionobjectundefined

  let  a = [1,2,3],
        b = 1,
        c = 'test',
        d = function(){console.log('test function')},
        e = true,
        f = null,
        g;

console.log(typeof(a));     //object
console.log(typeof(b));     //number
console.log(typeof(c));     //string
console.log(typeof(d));     //function
console.log(typeof(e));     //boolean
console.log(typeof(f));     //object
console.log(typeof(g));    //undefined

typeof的局限性: typeof在判断nullarrayobject以及函数实例(new + 函数)时,得到的都是object,这使得在判断这些数据类型的时候,得不到真是的数据类型。

 

instanceof


  instanceof用来检测某个对象是不是另一个对象的实例。

官方的话:该运算发用来测试一个对象在其原型链中是否存在一个构造函数prototype属性

instance中文翻译为实例,用来判断该对象是谁的实例,同时我们也就知道instanceof是对象运算符。

这里的实例就牵扯到了对象的继承,它的判断就是根据原型链进行搜寻,在对象obj1的原型链上如果存在另一个对象obj2的原型属性,那么表达式(obj1 instanceof obj2)返回值为true;否则返回false。
var a = new Array();

console.log(a instanceof Array);    // 会返回 true
console.log(a instanceof Object);    // 也会返回 true

因为Array是object 的子类

--------------------------------------------------------------

function Foo(){}
Foo.prototype = new Aoo();  // 原型继承
var foo = new Foo();
console.log(foo instanceof Foo)  //true
console.log(foo instanceof Aoo)  //true

instanceof不仅可以判断一层继承关系,也可以判断多层继承关系

--------------------------------------------------------------

var a = new Array();
if(a instanceof Object)              // 返回true
if(window instanceof Object)    // 返回false

typeof(window)  //会得到object

需要注意的是,如果表达式 obj instanceof Foo 返回true,则并不意味着该表达式会永远返回ture,因为Foo.prototype属性的值有可能会改变,改变之后的值很有可能不存在于obj的原型链上,这时原表达式的值就会成为false

 

总结:


 

 

typeof和instanceof都是用来判断变量类型的,两者的区别在于:

  • typeof判断所有变量的类型,返回值有number,boolean,string,function,object,undefined。
  • typeof对于丰富的对象实例,只能返回"Object"字符串。
  • instanceof用来判断对象,代码形式为obj1 instanceof obj2(obj1是否是obj2的实例),obj2必须为对象,否则会报错!其返回值为布尔值。
  • instanceof可以对不同的对象实例进行判断,判断方法是根据对象的原型链依次向下查询,如果obj2的原型属性存在obj1的原型链上,(obj1 instanceof obj2)值为true。

 

补充:


 

使用 Object.prototype.tostring.call(obj) 检测对象类型 

先看使用示例

console.log(Object.prototype.toString.call("jerry"));//[object String]
console.log(Object.prototype.toString.call(12));//[object Number]
console.log(Object.prototype.toString.call(true));//[object Boolean]
console.log(Object.prototype.toString.call(undefined));//[object Undefined]
console.log(Object.prototype.toString.call(null));//[object Null]
console.log(Object.prototype.toString.call({name: "jerry"}));//[object Object]
console.log(Object.prototype.toString.call(function(){}));//[object Function]
console.log(Object.prototype.toString.call([]));//[object Array]
console.log(Object.prototype.toString.call(new Date));//[object Date]
console.log(Object.prototype.toString.call(/\d/));//[object RegExp]
function Person(){};
console.log(Object.prototype.toString.call(new Person));//[object Object]

为什么这样就能区分呢?于是我去看了一下toString方法的用法:toString方法返回反映这个对象的字符串。

那为什么不直接用obj.toString()呢?

console.log("jerry".toString());//jerry
console.log((1).toString());//1
console.log([1,2].toString());//1,2
console.log(new Date().toString());//Wed Dec 21 2016 20:35:48 GMT+0800 (中国标准时间)
console.log(function(){}.toString());//function (){}
console.log(null.toString());//error
console.log(undefined.toString());//error

同样是检测对象obj调用toString方法,obj.toString()的结果和Object.prototype.toString.call(obj)的结果不一样,这是为什么?

        这是因为toString为Object的原型方法,而Array 、Function等类型作为Object的实例,都重写了toString方法。不同的对象类型调用toString方法时,根据原型链的知识,调用的是对应的重写之后的toString方法(Function类型返回内容为函数体的字符串,Array类型返回元素组成的字符串.....),而不会去调用Object上原型toString方法(返回对象的具体类型),所以采用obj.toString()不能得到其对象类型,只能将obj转换为字符串类型;因此,在想要得到对象的具体类型时,应该调用Object上原型toString方法。

我们可以验证一下,将数组的toString方法删除,看看会是什么结果:

var arr=[1,2,3];
console.log(Array.prototype.hasOwnProperty("toString"));//true
console.log(arr.toString());//1,2,3
delete Array.prototype.toString;//delete操作符可以删除实例属性
console.log(Array.prototype.hasOwnProperty("toString"));//false
console.log(arr.toString());//"[object Array]"

删除了Array的toString方法后,同样再采用arr.toString()方法调用时,不再有屏蔽Object原型方法的实例方法,因此沿着原型链,arr最后调用了Object的toString方法,返回了和Object.prototype.toString.call(arr)相同的结果。

 

上一篇:09.js类型转换


下一篇:11强制类型转换