你该知道的JS知识---数据类型判断

88 阅读3分钟

数据类型概况

在JS里面数据类型可以分成两种:

  • 基础数据类型:string,number,boolean,undefined,null和Symbol
  • 引用数据类型:Object(其中Object又包括Array,RegExp,Date,Math,Function)

为什么会有基础数据类型和引用数据类型?
这是因为它们两种数据类型存储在不同的内存中,因此上面的数据类型分成两类来存储:

  • 基础数据类型存储在栈内存中,被引用或拷贝时,会创建一个完全相等的变量
  • 引用数据类型在栈内存里有指向堆内存的内存地址,多个引用可能指向同一个内存地址,从而数据也发生了共享
var a={
    name:'张三',
    age:'18'
}
var b=a
console.log(a.name)  //'张三'
b.name='李四'
console.log(a.name)  //'李四'
console.log(b.name)  //'李四'

我们改变了b.name之后,a.name也随着发生了改变,这是因为a是引用数据类型,声明的变量b直接等于a,b直接引用a的内存地址

var a={
    name:'张三',
    age:'18'
}
var b=foo(a)
function foo(data){
    data.name:'李四'
    data={
        name:'王五',
        age:19
    }
    return data
}
console.log(a)  //{name:'李四',age:18}
console.log(b)  //{name:'王五',age:19}

在这个例子中,我们可以看到a传给了foo函数,在foo函数里我们改变了它的name属性,在函数里面的data.name还是和a.name引用同一个内存地址,因此name属性值被改变了。但是b变量的值等于一个函数的返回值,return返回的是一个新的对象,开辟了一块新的内存地址。

数据类型检测

方法一:typeof

typeof 1                //'number'
typeof '1'              //'string'
typeof undefined        //'undefined'
typeof true             //'boolean'
typeof Symbol()         //'symbol'
typeof null            //'object'
typeof []              //'object'
typeof {}             //'object'
typeof console       //'object'
typeof console.log   //'function'
typeof Function      //'function'
typeof Array        //'function'

在以上例子可以看出,基本数据类型使用typeof可以精准的检测出来(null除外),对于引用数据类型不能准确检测出来
方法二:instanceof
我们通过new实例化构造函数,创建一个新的对象,这个新对象继承来构造函数的方法,通过原型链向上可以找到,而instanceof就可以判断出这个对象是不是由之前的构造函数创建出来的对象,这样就可以判断出新对象的数据类型

var Car=function(){}
var car=new Car()
car instanceof Car    //true

var a=new String('abc')
a instanceof String    //true

var str='abc'
str instanceof String  //false

由上面的代码可知,car是通过实例化Car这个构造函数创建出来的对象,因此car能够使用instanceof向上找到自己的构造函数原型Car;a通过new String() 实例化出来的字符串,因此也在String的原型上;但是对于简单数据类型的检测,instanceof 是无法做到的

//手写instanceof 
function myInstanceOf(obj,type){
    //如果obj不为对象或者为null,则不能检测
    if(typeof obj!=='object'||object===null) return false
    var proto=Object.getPrototypeOf(obj)
    while(true){
        if(proto===null) return false
        else if(proto===type.prototype) return true
        proto=Object.getPrototypeOf(proto)
    }
}
myInstanceOf(new String('abc'),String)  //true
myInstanceOf(123,Number)  //false

方法三:Object.prototype.toSring.call(obj) toSting()是Object原型上的方法,调用方法,返回字符串'[object Xxx]',Xxx就是对象的类型。对于Object对象,直接调用toString()方法,就会返回'[object Object]',但是对于其他类型,需要通过call()方法来调用,才能返回正确信息。

Object.prototype.toString({})       // "[object Object]"

Object.prototype.toString.call(123)    // "[object Number]"

Object.prototype.toString.call('')  // "[object String]"

Object.prototype.toString.call(true)  // "[object Boolean]"

Object.prototype.toString.call(function(){})  // "[object Function]"

Object.prototype.toString.call(null)   //"[object Null]"

Object.prototype.toString.call(undefined) //"[object Undefined]"

Object.prototype.toString.call(/123/g)    //"[object RegExp]"

Object.prototype.toString.call(new Date()) //"[object Date]"

Object.prototype.toString.call([])       //"[object Array]"

Object.prototype.toString.call(document)  //"[object HTMLDocument]"

Object.prototype.toString.call(window)   //"[object Window]"

注意typeof检测出来出来的类型,首字母是小写的,而使用toString()方法检测出来的对象类型'Xxx',首字母是大写
那么如何直接取出检测出来的类型? 我们可以直接使用Object.prototype.toString.call(obj).slice(8,-1)可以直接得到。