js-数据类型判断以及instanceof实现

444 阅读3分钟

数据类型

  • 基本数据类型:存储在栈(stack)中的简单数据段,也就是说,它们的值直接存储在变量访问的位置。 这是因为这些原始类型占据的空间是固定的,所以可将他们存储在较小的内存区域 – 栈中。这样存储便于迅速查寻变量的值。

  • 引用数据类型:存储在堆(heap)中的对象,也就是说,存储在变量处的值是一个指针(point),指向存储对象的内存地址。 这是因为:引用值的大小会改变,所以不能把它放在栈中,否则会降低变量查寻的速度。相反,放在变量的栈空间中的值是该对象存储在堆中的地址。地址的大小是固定的,所以把它存储在栈中对变量性能无任何负面影响。

js数据类型

  • 基本数据类型 string,number,boolean,null,undefined,symbol
  • 引用数据类型: object, function, array,Reg

typeof

  • typeof返回一个字符串,表示未经计算的操作数类型

  • 判断基本数据类型。特例:null的操作数类型是object

  • 引用数据类型返回object,特例:function(){} 返回function

console.log(typeof 11) // number
console.log(typeof '11') // string
console.log(typeof true) // boolean
console.log(typeof undefined) // undefined
console.log(typeof []) // object
console.log(typeof {}) // object
console.log(typeof function name(params) {}) // function 
console.log(typeof null) // object

instanceof作用

  • A instanceof B 某对象是否是构造函数的实例(玩的是原型链)

  • 所以基本数据类型返回false,对象(引用数据类型)返回true

步骤概念

  1. 由于instance要检测是是,某对象。所以一定要有一个前置判断条件
  2. 左侧的__proto 是否和右侧的prototype一致。对象是否是构造函数的实例
  3. 如果不一致,会一直往上找。如果找到返回false,找不到,返回true
    function _instanceof(L, R) {
        if (L === null) {
            return false
        }
        if (typeof L !== 'object' && typeof L !== 'function') return false
        L = L.__proto__
        R = R.prototype
        while (L) {
            if (L === null) return false
            if (L === R) return true
            L = L.__proto__
        }
    }
    console.log('检测', _instanceof(null, Array)) // false
    console.log('检测', _instanceof([], Array)) // true
    console.log('检测', _instanceof('', Array)) // false
    console.log('检测', _instanceof({}, Object)) // true

Object.prototype.toString.call()

 console.log(Object.prototype.toString.call([])) // [object Object]
    console.log(Object.prototype.toString.call({})) // [object Boolean]
    console.log(Object.prototype.toString.call(true))// [object Boolean]
    console.log(Object.prototype.toString.call(null))// [object Null]
    console.log(Object.prototype.toString.call(undefined))// [object Undefined]
    console.log(Object.prototype.toString.call('11'))// [object String]
    console.log(Object.prototype.toString.call(11))// [object Number]
    console.log(Object.prototype.toString.call(function () { }))// [object Function]

Object.prototype.toString 讲解

  • Object.prototype.toString 会返回一个形如"[object XXX]"的字符串
  • 对于Object.prototype.toString.call(arg),若参数为null或undefined,直接返回结果。
  • 若参数不为null或undefined,则将参数转为对象,再作判断。对于原始类型,转为对象的方法即装箱,此处不赘述。
  • 转为对象后,取得该对象的[Symbol.toStringTag]属性值(可能会遍历原型链)作为tag,如无该属性,或该属性值不为字符串类型,则依下表取得tag, 然后返回"[object " + tag + "]"形式的字符串。

封装成一个通用的方法

function getType(obj) {
        let type = Object.prototype.toString.call(obj)
        return type.split(' ')[1].replace(']', '')
    }
    console.log('检测', getType({})) // Object
    console.log('检测', getType([])) // Arrary
    console.log('检测', getType('11')) // String
    console.log('检测', getType(11)) // Number

总结

  • typeof是小老弟,返回具体的数据类型,用来区分基本数据类型完全可以够用。但是用来区分引用数据类型就jj了

  • instanceof是专门用来判断引用数据类型的,是引用类型就返回true。不是就返回false。在手写instanceof的时候,配合上typeof,可以说就完美的解决了判断基本数据类型和引用数据类型。

  • 万物皆对象,所以最后高明的Object出现了,他基本类型和引用类型都能判断,并且以[object xxx]的形式。返回具体的数据类型

  • 说到最后,程序员是写代码的,你们type,instanceof,Object.prototype.toString.cal.终究不过是工具。我们封装一个方法,直接调用方法求类型多方便。