JS中数据类型的判断( typeof,instanceof,constructor,Object.prototype.toString.call()区别)

js判断数据类型很有多种方法,下面主要说下 typeof,instanceof,constructor,Object.prototype.toString.call()区别!

1.typeof

这个最熟悉不过了,判断数据类型很常用的方法!但是它都能判断什么数据类型呢?

console.log(typeof 2);//number
console.log(typeof "2");//string
console.log(typeof true);//boolean
console.log(typeof undefined);//underfined
console.log(typeof null);//object
console.log(typeof function(){});//Function
console.log(typeof [1,2,3]);//object
console.log(typeof {p:1});//object

很明显的看出,基本类型除非了null判断类型是object外,其他的都能很准确的作出判断,然后引用类型除非了functrion 能够准备判断出类型,其他判断都是object类型!
结论:基本类型可以作出准确判断(null除外),也不能很准确的判断出引用类型!

2.instanceof

这个应该见过,但是用的可能不是很多,a instranceof b,意思判断 b的原型对象是否在a的原型链上!
我们来模拟下它的原理!

function instanceOfTest(a, b) {
         var bp = b.prototype;
         var ap = a.__proto__;//在原型链上找原型对象
         while (true) {
             if (ap === bp) {// 相等就说明在原型链上找到b的原型了
                 return true;
             } else if (ap === null) {//找到尽头了,确实没有
                 return false;
             }
             ap = ap.__proto__; //没找到,一直往上找
         };
     };
console.log(instanceOfTest([], Object)); //true
console.log([] instanceof Object);//true

注释写的很清楚,也很直观的代码!那么它能做什么呢?它可以判断引用类型,基本类型判断不了(下面会讲原因),先看看怎么判断引用类型的

console.log([] instanceof Array);//true
console.log({} instanceof Object);//true
console.log(function(){} instanceof Function);//true

看上去好像没啥问题,但是如果后面是Object的话,那么都返回true,因为Object是它们的祖师爷了!

console.log([] instanceof Object);//true
console.log({} instanceof Object);//true
console.log(function(){} instanceof Object);//true

再来看看基本类型的

var a =1;
console.log(a instanceof Number);//false
console.log(a.constructor === Number);//true

这里有个坑!其实 a是Number的实例,Number的原型也在a的原型链上!为什么 a instanceof Number结果是false? 其实是 object instranceof constructor ,注意看!是object,如果不是object全部返false,那么问题来了?为什么实例出来的对象变成了基本类型?很懵!!! 其实当我们字面量创建变量时候,后台就会创建一个对应的基本包装类型的对象,下面是它的创建过程!
1.创建String的实例
2.在实例上调用指定的方法
3.销毁这个实例

var a = "1234" 
//等价于
var a = new Number("1234");
var copyA = a.substr(0);
a = null;

这个过程是非常短暂的,这个也是引用类型和包装类型的最大区别,也就是对象的生命周期,在运行的一瞬间就被销毁了,这个也是为什么在运行的时候在包装对象上添加不了属性和方法

var a = "1234"
a.add = "add";
console.log(a);//underfined

知道了这个原理,那么上面疑惑也应该解决了!

3.constructor

顾名思义构造函数,肯定是指向构造函数,在原型上才有这个属性,由于实例出来的对象会继承原型上的属性,所以也有这个属性

console.log((1).constructor ===Number);//true
console.log(true.constructor === Boolean);//true
console.log("1".constructor === String);//true
console.log([].constructor === Array);//true
console.log(function(){}.constructor === Function);//true
console.log({}.constructor === Object);//true

这里有一点需要注意,当直接给原型赋值后,那么constructor指向就会改变!

function A(){

};
var p =new A();
console.log(p.constructor===A);//true
A.prototype = [];
var p1 =new A();
console.log(p1.constructor===A);//false
console.log(p1.constructor===Array);//true
4.Object.prototype.toString.call()

这个是推荐使用的,能够比较精准的判断各种类型,原理是借用Object原型上的toString()方法!

var test = Object.prototype.toString;
console.log(test.call(1));//[object Number]
console.log(test.call("1"));//[object String]
console.log(test.call(true));//[object Boolean]
console.log(test.call(function(){}));//[object Function]
console.log(test.call(undefined));//[object Undefined]
console.log(test.call(null));//[object Null]
console.log(test.call([]));//[object Array]
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章